diff --git a/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java b/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java index 3d0f4c2c360..359065d732b 100644 --- a/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java +++ b/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java @@ -66,10 +66,6 @@ public Container.ExecResult execInContainer(InspectContainerResponse containerIn DockerClient dockerClient = DockerClientFactory.instance().client(); - dockerClient - .execCreateCmd(containerId) - .withCmd(command); - log.debug("{}: Running \"exec\" command: {}", containerName, String.join(" ", command)); final ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId) .withAttachStdout(true).withAttachStderr(true).withCmd(command).exec(); diff --git a/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java b/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java index 2013ddc4d9c..9b4be81b4c4 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java +++ b/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java @@ -29,7 +29,7 @@ public Boolean call() { for (int internalPort : internalPorts) { command += " && "; command += " ("; - command += format("cat /proc/net/tcp* | awk '{print $2}' | grep -i :%x", internalPort); + command += format("cat /proc/net/tcp* | awk '{print $2}' | grep -i ':0*%x'", internalPort); command += " || "; command += format("nc -vz -w 1 localhost %d", internalPort); command += " || "; diff --git a/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java b/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java index bee4f0a231a..00c0bc9d1ef 100644 --- a/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java +++ b/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java @@ -3,23 +3,47 @@ import com.google.common.collect.ImmutableSet; import org.junit.Rule; import org.junit.Test; -import org.testcontainers.containers.BindMode; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.rnorth.ducttape.TimeoutException; +import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import java.util.concurrent.TimeUnit; + +import static java.util.Arrays.asList; import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; +@RunWith(Parameterized.class) public class InternalCommandPortListeningCheckTest { - // Linking a custom configuration into the container so that nginx is listening on port 8080. This is necessary to prove - // that the command formatting uses the correct casing for hexadecimal numbers (i.e. 1F90 and not 1f90). + @Parameterized.Parameters(name = "{index} - {0}") + public static Iterable data() { + return asList( + new Object[][]{ + {"internal-port-check-dockerfile/Dockerfile-tcp"}, + {"internal-port-check-dockerfile/Dockerfile-nc"}, + {"internal-port-check-dockerfile/Dockerfile-bash"}, + }); + } + @Rule - public GenericContainer nginx = new GenericContainer<>("nginx:1.9.4") - .withClasspathResourceMapping("nginx_on_8080.conf", "/etc/nginx/conf.d/default.conf", BindMode.READ_ONLY); + public GenericContainer container; + + public InternalCommandPortListeningCheckTest(String dockerfile) { + container = new GenericContainer(new ImageFromDockerfile() + .withFileFromClasspath("Dockerfile", dockerfile) + .withFileFromClasspath("nginx.conf", "internal-port-check-dockerfile/nginx.conf") + ); + } @Test public void singleListening() { - final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(nginx, ImmutableSet.of(8080)); + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(8080)); + + Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); final Boolean result = check.call(); @@ -28,10 +52,27 @@ public void singleListening() { @Test public void nonListening() { - final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(nginx, ImmutableSet.of(8080, 1234)); + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(8080, 1234)); + + try { + Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); + } catch (TimeoutException e) { + // we expect it to timeout + } final Boolean result = check.call(); assertFalse("InternalCommandPortListeningCheck detects a non-listening port among many", result); } + + @Test + public void lowAndHighPortListening() { + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(100, 8080)); + + Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); + + final Boolean result = check.call(); + + assertTrue("InternalCommandPortListeningCheck identifies a low and a high port", result); + } } diff --git a/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-bash b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-bash new file mode 100644 index 00000000000..02373da980e --- /dev/null +++ b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-bash @@ -0,0 +1,11 @@ +FROM nginx:1.17-alpine + +RUN apk add bash + +# Make sure the /proc/net/tcp* check fails in this container +RUN rm /usr/bin/awk + +# Make sure the nc check fails in this container +RUN rm /usr/bin/nc + +ADD nginx.conf /etc/nginx/conf.d/default.conf diff --git a/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-nc b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-nc new file mode 100644 index 00000000000..f69b74a8754 --- /dev/null +++ b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-nc @@ -0,0 +1,9 @@ +FROM nginx:1.17-alpine + +# If this fails, you ended up using a base image with bash installed. Consider removing /bin/bash in this case +RUN if bash -c true &> /dev/null; then exit 1; fi + +# Make sure the /proc/net/tcp* check fails in this container +RUN rm /usr/bin/awk + +ADD nginx.conf /etc/nginx/conf.d/default.conf diff --git a/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-tcp b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-tcp new file mode 100644 index 00000000000..8699db537aa --- /dev/null +++ b/core/src/test/resources/internal-port-check-dockerfile/Dockerfile-tcp @@ -0,0 +1,9 @@ +FROM nginx:1.17-alpine + +# If this fails, you ended up using a base image with bash installed. Consider removing /bin/bash in this case +RUN if bash -c true &> /dev/null; then exit 1; fi + +# Make sure the nc check fails in this container +RUN rm /usr/bin/nc + +ADD nginx.conf /etc/nginx/conf.d/default.conf diff --git a/core/src/test/resources/internal-port-check-dockerfile/nginx.conf b/core/src/test/resources/internal-port-check-dockerfile/nginx.conf new file mode 100644 index 00000000000..f69ddf345cf --- /dev/null +++ b/core/src/test/resources/internal-port-check-dockerfile/nginx.conf @@ -0,0 +1,8 @@ +# This configuration makes Nginx listen on port port 8080 + +server { + # Port 8080 is necessary to prove that the command formatting in the /proc/net/tcp* check uses the correct casing for hexadecimal numbers (i.e. 1F90 and not 1f90) + listen 8080; + # Port 100 is necessary to ensure that the /proc/net/tcp* check also succeeds with trailing zeros in the hexadecimal port + listen 100; +} diff --git a/core/src/test/resources/nginx_on_8080.conf b/core/src/test/resources/nginx_on_8080.conf deleted file mode 100644 index c7927d46265..00000000000 --- a/core/src/test/resources/nginx_on_8080.conf +++ /dev/null @@ -1,5 +0,0 @@ -# This configuration makes Nginx listen on port port 8080 - -server { - listen 8080; -} \ No newline at end of file