diff --git a/core/src/main/java/org/testcontainers/DockerClientFactory.java b/core/src/main/java/org/testcontainers/DockerClientFactory.java index 54f44dbed3c..0ca7d41a209 100644 --- a/core/src/main/java/org/testcontainers/DockerClientFactory.java +++ b/core/src/main/java/org/testcontainers/DockerClientFactory.java @@ -62,8 +62,12 @@ public class DockerClientFactory { private static DockerClientFactory instance; // Cached client configuration - private DockerClientProviderStrategy strategy; - private boolean initialized = false; + @VisibleForTesting + DockerClientProviderStrategy strategy; + + @VisibleForTesting + DockerClient dockerClient; + private String activeApiVersion; private String activeExecutionDriver; @@ -74,10 +78,8 @@ public class DockerClientFactory { System.setProperty("org.testcontainers.shaded.io.netty.packagePrefix", "org.testcontainers.shaded."); } - /** - * Private constructor - */ - private DockerClientFactory() { + @VisibleForTesting + DockerClientFactory() { } @@ -98,6 +100,19 @@ public synchronized static DockerClientFactory instance() { return instance; } + @Synchronized + private DockerClientProviderStrategy getOrInitializeStrategy() { + if (strategy != null) { + return strategy; + } + + List configurationStrategies = new ArrayList<>(); + ServiceLoader.load(DockerClientProviderStrategy.class).forEach(configurationStrategies::add); + + strategy = DockerClientProviderStrategy.getFirstValidStrategy(configurationStrategies); + return strategy; + } + /** * * @return a new initialized Docker client @@ -105,63 +120,57 @@ public synchronized static DockerClientFactory instance() { @Synchronized public DockerClient client() { - if (strategy != null) { - return strategy.getClient(); + if (dockerClient != null) { + return dockerClient; } - List configurationStrategies = new ArrayList(); - ServiceLoader.load(DockerClientProviderStrategy.class).forEach( cs -> configurationStrategies.add( cs ) ); - - strategy = DockerClientProviderStrategy.getFirstValidStrategy(configurationStrategies); + final DockerClientProviderStrategy strategy = getOrInitializeStrategy(); String hostIpAddress = strategy.getDockerHostIpAddress(); log.info("Docker host IP address is {}", hostIpAddress); - DockerClient client = strategy.getClient(); - - if (!initialized) { - Info dockerInfo = client.infoCmd().exec(); - Version version = client.versionCmd().exec(); - activeApiVersion = version.getApiVersion(); - activeExecutionDriver = dockerInfo.getExecutionDriver(); - log.info("Connected to docker: \n" + - " Server Version: " + dockerInfo.getServerVersion() + "\n" + - " API Version: " + activeApiVersion + "\n" + - " Operating System: " + dockerInfo.getOperatingSystem() + "\n" + - " Total Memory: " + dockerInfo.getMemTotal() / (1024 * 1024) + " MB"); - - String ryukContainerId = null; - boolean useRyuk = !Boolean.parseBoolean(System.getenv("TESTCONTAINERS_RYUK_DISABLED")); - if (useRyuk) { - ryukContainerId = ResourceReaper.start(hostIpAddress, client); - log.info("Ryuk started - will monitor and terminate Testcontainers containers on JVM exit"); - } + final DockerClient client = strategy.getClient(); + + Info dockerInfo = client.infoCmd().exec(); + Version version = client.versionCmd().exec(); + activeApiVersion = version.getApiVersion(); + activeExecutionDriver = dockerInfo.getExecutionDriver(); + log.info("Connected to docker: \n" + + " Server Version: " + dockerInfo.getServerVersion() + "\n" + + " API Version: " + activeApiVersion + "\n" + + " Operating System: " + dockerInfo.getOperatingSystem() + "\n" + + " Total Memory: " + dockerInfo.getMemTotal() / (1024 * 1024) + " MB"); + + String ryukContainerId = null; + boolean useRyuk = !Boolean.parseBoolean(System.getenv("TESTCONTAINERS_RYUK_DISABLED")); + if (useRyuk) { + ryukContainerId = ResourceReaper.start(hostIpAddress, client); + log.info("Ryuk started - will monitor and terminate Testcontainers containers on JVM exit"); + } - boolean checksEnabled = !TestcontainersConfiguration.getInstance().isDisableChecks(); - if (checksEnabled) { - VisibleAssertions.info("Checking the system..."); - checkDockerVersion(version.getVersion()); - if (ryukContainerId != null) { - checkDiskSpace(client, ryukContainerId); - } else { - runInsideDocker( - client, - createContainerCmd -> { - createContainerCmd.withName("testcontainers-checks-" + SESSION_ID); - createContainerCmd.getHostConfig().withAutoRemove(true); - createContainerCmd.withCmd("tail", "-f", "/dev/null"); - }, - (__, containerId) -> { - checkDiskSpace(client, containerId); - return ""; - } - ); - } + boolean checksEnabled = !TestcontainersConfiguration.getInstance().isDisableChecks(); + if (checksEnabled) { + VisibleAssertions.info("Checking the system..."); + checkDockerVersion(version.getVersion()); + if (ryukContainerId != null) { + checkDiskSpace(client, ryukContainerId); + } else { + runInsideDocker( + client, + createContainerCmd -> { + createContainerCmd.withName("testcontainers-checks-" + SESSION_ID); + createContainerCmd.getHostConfig().withAutoRemove(true); + createContainerCmd.withCmd("tail", "-f", "/dev/null"); + }, + (__, containerId) -> { + checkDiskSpace(client, containerId); + return ""; + } + ); } - - initialized = true; } - return client; + dockerClient = client; + return dockerClient; } private void checkDockerVersion(String dockerVersion) { @@ -237,15 +246,12 @@ public void checkAndPullImage(DockerClient client, String image) { * @return the IP address of the host running Docker */ public String dockerHostIpAddress() { - return strategy.getDockerHostIpAddress(); + return getOrInitializeStrategy().getDockerHostIpAddress(); } public T runInsideDocker(Consumer createContainerCmdConsumer, BiFunction block) { - if (strategy == null) { - client(); - } // We can't use client() here because it might create an infinite loop - return runInsideDocker(strategy.getClient(), createContainerCmdConsumer, block); + return runInsideDocker(getOrInitializeStrategy().getClient(), createContainerCmdConsumer, block); } private T runInsideDocker(DockerClient client, Consumer createContainerCmdConsumer, BiFunction block) { @@ -293,9 +299,7 @@ DiskSpaceUsage parseAvailableDiskSpace(String dfOutput) { * @return the docker API version of the daemon that we have connected to */ public String getActiveApiVersion() { - if (!initialized) { - client(); - } + client(); return activeApiVersion; } @@ -303,9 +307,7 @@ public String getActiveApiVersion() { * @return the docker execution driver of the daemon that we have connected to */ public String getActiveExecutionDriver() { - if (!initialized) { - client(); - } + client(); return activeExecutionDriver; } @@ -314,7 +316,7 @@ public String getActiveExecutionDriver() { * @return whether or not the currently active strategy is of the provided type */ public boolean isUsing(Class providerStrategyClass) { - return providerStrategyClass.isAssignableFrom(this.strategy.getClass()); + return strategy != null && providerStrategyClass.isAssignableFrom(this.strategy.getClass()); } private static class NotEnoughDiskSpaceException extends RuntimeException { diff --git a/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java b/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java index e13c3875f31..19a591be919 100644 --- a/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java +++ b/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java @@ -7,6 +7,8 @@ import org.testcontainers.dockerclient.LogToStringContainerCallback; import org.testcontainers.utility.TestcontainersConfiguration; +import static org.assertj.core.api.Assertions.assertThat; + /** * Test for {@link DockerClientFactory}. */ @@ -43,4 +45,11 @@ public void shouldHandleBigDiskSize() throws Exception { VisibleAssertions.assertEquals("Available MB is correct", 2982480572L / 1024L, usage.availableMB.orElse(0L)); VisibleAssertions.assertEquals("Available percentage is correct", 31, usage.usedPercent.orElse(0)); } -} \ No newline at end of file + + @Test + public void dockerHostIpAddress() { + DockerClientFactory instance = new DockerClientFactory(); + instance.strategy = null; + assertThat(instance.dockerHostIpAddress()).isNotNull(); + } +} diff --git a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java index e4e29550b9c..2e88982a7a8 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; public class DockerClientConfigUtilsTest { @@ -33,7 +34,7 @@ public void getDockerHostIpAddressShouldReturnDockerHostIpWhenHttpsUri() { String actual = DockerClientConfigUtils.getDockerHostIpAddress(configuration); assertEquals("12.23.34.45", actual); } - + @Test public void getDockerHostIpAddressShouldReturnDockerHostIpWhenTcpUri() { DockerClientConfig configuration = DefaultDockerClientConfig.createDefaultConfigBuilder() @@ -43,11 +44,16 @@ public void getDockerHostIpAddressShouldReturnDockerHostIpWhenTcpUri() { String actual = DockerClientConfigUtils.getDockerHostIpAddress(configuration); assertEquals("12.23.34.45", actual); } - + @Test @Ignore public void getDockerHostIpAddressShouldReturnNullWhenUnsupportedUriScheme() { DockerClientConfig configuration = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("gopher://12.23.34.45").build(); String actual = DockerClientConfigUtils.getDockerHostIpAddress(configuration); assertNull(actual); } + + @Test(timeout = 5_000) + public void getDefaultGateway() { + assertNotNull(DockerClientConfigUtils.getDefaultGateway()); + } }