diff --git a/core/src/main/java/org/testcontainers/containers/Container.java b/core/src/main/java/org/testcontainers/containers/Container.java index 002d5163acd..b3c0a5298da 100644 --- a/core/src/main/java/org/testcontainers/containers/Container.java +++ b/core/src/main/java/org/testcontainers/containers/Container.java @@ -388,15 +388,35 @@ ExecResult execInContainer(Charset outputCharset, String... command) void setLinkedContainers(Map linkedContainers); + /** + * @deprecated set by GenericContainer and should never be set outside + */ + @Deprecated void setDockerClient(DockerClient dockerClient); + /** + * @deprecated set by GenericContainer and should never be set outside + */ + @Deprecated void setDockerDaemonInfo(Info dockerDaemonInfo); + /** + * @deprecated set by GenericContainer and should never be set outside + */ + @Deprecated void setContainerId(String containerId); + /** + * @deprecated set by GenericContainer and should never be set outside + */ + @Deprecated void setContainerName(String containerName); void setWaitStrategy(WaitStrategy waitStrategy); + /** + * @deprecated set by GenericContainer and should never be set outside + */ + @Deprecated void setContainerInfo(InspectContainerResponse containerInfo); } diff --git a/core/src/main/java/org/testcontainers/containers/GenericContainer.java b/core/src/main/java/org/testcontainers/containers/GenericContainer.java index 4f1d45f9c44..ed8ca612f3c 100644 --- a/core/src/main/java/org/testcontainers/containers/GenericContainer.java +++ b/core/src/main/java/org/testcontainers/containers/GenericContainer.java @@ -58,7 +58,7 @@ @EqualsAndHashCode(callSuper = false) public class GenericContainer> extends FailureDetectingExternalResource - implements Container { + implements Container, AutoCloseable { private static final Charset UTF8 = Charset.forName("UTF-8"); @@ -134,6 +134,8 @@ public class GenericContainer> private List> logConsumers = new ArrayList<>(); + private final Set> createContainerCmdModifiers = new LinkedHashSet<>(); + private static final Set AVAILABLE_IMAGE_NAME_CACHE = new HashSet<>(); private static final RateLimiter DOCKER_CLIENT_RATE_LIMITER = RateLimiterBuilder .newBuilder() @@ -191,6 +193,7 @@ private void tryStart(Profiler profiler) { profiler.start("Create container"); CreateContainerCmd createCommand = dockerClient.createContainerCmd(dockerImageName); applyConfiguration(createCommand); + createContainerCmdModifiers.forEach(hook -> hook.accept(createCommand)); containerId = createCommand.exec().getId(); ResourceReaper.instance().registerContainerForCleanup(containerId, dockerImageName); @@ -881,6 +884,24 @@ public void withStartupAttempts(int attempts) { this.startupAttempts = attempts; } + @Override + public void close() { + stop(); + } + + /** + * Allow low level modifications of {@link CreateContainerCmd} after it was pre-configured in {@link #tryStart(Profiler)}. + * Invocation happens eagerly on a moment when container is created. + * Warning: this does expose the underlying docker-java API so might change outside of our control. + * + * @param modifier {@link Consumer} of {@link CreateContainerCmd}. + * @return this + */ + public SELF withCreateContainerCmdModifier(Consumer modifier) { + createContainerCmdModifiers.add(modifier); + return self(); + } + /** * Convenience class with access to non-public members of GenericContainer. */ diff --git a/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java b/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java index f91ad463444..59d9cb2b34f 100644 --- a/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java +++ b/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java @@ -11,6 +11,7 @@ import org.rnorth.ducttape.RetryCountExceededException; import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.Base58; import org.testcontainers.utility.TestEnvironment; import java.io.*; @@ -282,6 +283,26 @@ public void extraHostTest() throws IOException { assertTrue("The hosts file of container contains extra host", matcher.find()); } + @Test + public void createContainerCmdHookTest() { + // Use random name to avoid the conflicts between the tests + String randomName = Base58.randomString(5); + try( + GenericContainer container = new GenericContainer<>("redis:3.0.2") + .withCommand("redis-server", "--help") + .withCreateContainerCmdModifier(cmd -> cmd.withName("overrideMe")) + // Preserves the order + .withCreateContainerCmdModifier(cmd -> cmd.withName(randomName)) + // Allows to override pre-configured values by GenericContainer + .withCreateContainerCmdModifier(cmd -> cmd.withCmd("redis-server", "--port", "6379")) + ) { + container.start(); + + assertEquals("Name is configured", "/" + randomName, container.getContainerInfo().getName()); + assertEquals("Command is configured", "[redis-server, --port, 6379]", Arrays.toString(container.getContainerInfo().getConfig().getCmd())); + } + } + private BufferedReader getReaderForContainerPort80(GenericContainer container) { return Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, () -> {