From ef5c972e01bd13eb7d1a98e7d479c1ad4921ae15 Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Tue, 25 Oct 2016 16:25:10 +0300 Subject: [PATCH 1/4] Use command-based port check in HostPortWaitStrategy in case of Docker for Mac, Fixes #160 --- .../containers/wait/HostPortWaitStrategy.java | 72 ++++++++++++++++--- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java index d13d8ebf3ed..e46155e1002 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java @@ -1,13 +1,17 @@ package org.testcontainers.containers.wait; +import lombok.extern.slf4j.Slf4j; import org.rnorth.ducttape.TimeoutException; import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.Container; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.dockerclient.ProxiedUnixSocketClientProviderStrategy; -import java.io.IOException; import java.net.Socket; +import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** @@ -15,30 +19,82 @@ * * @author richardnorth */ +@Slf4j public class HostPortWaitStrategy extends GenericContainer.AbstractWaitStrategy { + + private static final String SUCCESS_MARKER = "TESTCONTAINERS_SUCCESS"; @Override protected void waitUntilReady() { final Integer port = getLivenessCheckPort(); if (null == port) { + log.debug("Liveness check port of {} is empty. Not waiting.", container.getContainerName()); return; } - final String ipAddress = container.getContainerIpAddress(); + Callable checkStrategy; + + // Special case for Docker for Mac, see #160 + if (DockerClientFactory.instance().isUsing(ProxiedUnixSocketClientProviderStrategy.class)) { + List exposedPorts = container.getExposedPorts(); + + Integer exposedPort = exposedPorts.stream() + .map(container::getMappedPort) + .filter(port::equals) + .findFirst() + .orElse(null); + + if (null == exposedPort) { + log.warn("Liveness check port of {} is set to {}, but it's not listed in exposed ports.", + container.getContainerName(), port); + return; + } + + String[][] commands = { + { "/bin/sh", "-c", "nc -vz -w 1 localhost " + exposedPort + " && echo " + SUCCESS_MARKER }, + { "/bin/bash", "-c", " { + for (String[] command : commands) { + try { + Container.ExecResult execResult = container.execInContainer(command); + + if (!execResult.getStderr().isEmpty()) { + log.warn(execResult.getStderr()); + } + if (execResult.getStdout().contains(SUCCESS_MARKER)) { + return true; + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (Exception e) { + continue; + } + } + + return false; + }; + } else { + checkStrategy = () -> { + new Socket(container.getContainerIpAddress(), port).close(); + return true; + }; + } + try { - Unreliables.retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - getRateLimiter().doWhenReady(() -> { + Unreliables.retryUntilTrue((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { + return getRateLimiter().getWhenReady(() -> { try { - new Socket(ipAddress, port).close(); - } catch (IOException e) { + return checkStrategy.call(); + } catch (Exception e) { throw new RuntimeException(e); } }); - return true; }); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for container port to open (" + - ipAddress + ":" + port + " should be listening)"); + container.getContainerIpAddress() + ":" + port + " should be listening)"); } } } From eb15c0945c38da54f55ba3e0aa0fffe40b14da89 Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Tue, 25 Oct 2016 16:35:14 +0300 Subject: [PATCH 2/4] remove debug logging --- .../containers/wait/HostPortWaitStrategy.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java index e46155e1002..48291672a35 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java @@ -4,7 +4,6 @@ import org.rnorth.ducttape.TimeoutException; import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.DockerClientFactory; -import org.testcontainers.containers.Container; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.GenericContainer; import org.testcontainers.dockerclient.ProxiedUnixSocketClientProviderStrategy; @@ -57,12 +56,7 @@ protected void waitUntilReady() { checkStrategy = () -> { for (String[] command : commands) { try { - Container.ExecResult execResult = container.execInContainer(command); - - if (!execResult.getStderr().isEmpty()) { - log.warn(execResult.getStderr()); - } - if (execResult.getStdout().contains(SUCCESS_MARKER)) { + if (container.execInContainer(command).getStdout().contains(SUCCESS_MARKER)) { return true; } } catch (InterruptedException e) { From af3704e32289056c224fa95de4427623d178762c Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Tue, 8 Nov 2016 10:32:34 +0200 Subject: [PATCH 3/4] fix port reversing in HostPortWaitStrategy --- .../testcontainers/containers/wait/HostPortWaitStrategy.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java index 48291672a35..743432eaeda 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/HostPortWaitStrategy.java @@ -37,8 +37,7 @@ protected void waitUntilReady() { List exposedPorts = container.getExposedPorts(); Integer exposedPort = exposedPorts.stream() - .map(container::getMappedPort) - .filter(port::equals) + .filter(it -> port.equals(container.getMappedPort(it))) .findFirst() .orElse(null); From b831fe8cefc93beac7b76d1aa35e82c1c8f2ec99 Mon Sep 17 00:00:00 2001 From: Sergei Egorov Date: Thu, 10 Nov 2016 08:20:51 +0200 Subject: [PATCH 4/4] change exec's log level to DEBUG from INFO --- .../java/org/testcontainers/containers/GenericContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/testcontainers/containers/GenericContainer.java b/core/src/main/java/org/testcontainers/containers/GenericContainer.java index 24c3415b6f2..aef42a82120 100644 --- a/core/src/main/java/org/testcontainers/containers/GenericContainer.java +++ b/core/src/main/java/org/testcontainers/containers/GenericContainer.java @@ -817,7 +817,7 @@ public ExecResult execInContainer(Charset outputCharset, String... command) .execCreateCmd(this.containerId) .withCmd(command); - logger().info("Running \"exec\" command: " + String.join(" ", command)); + logger().debug("Running \"exec\" command: " + String.join(" ", command)); final ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(this.containerId) .withAttachStdout(true).withAttachStderr(true).withCmd(command).exec();