Skip to content

Commit f5ec43d

Browse files
cdangerkiview
andauthored
Fixes the issue of missing root cause in container launch TimeoutException (e.g. SSLHandshakeException) (#5778)
Co-authored-by: Kevin Wittek <[email protected]>
1 parent 7ba6b1c commit f5ec43d

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ protected void waitUntilReady() {
319319
"Timed out waiting for URL to be accessible (%s should return HTTP %s)",
320320
uri,
321321
statusCodes.isEmpty() ? HttpURLConnection.HTTP_OK : statusCodes
322-
)
322+
),
323+
e
323324
);
324325
}
325326
}

core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.testcontainers.junit.wait.strategy;
22

3+
import org.assertj.core.api.Assertions;
34
import org.jetbrains.annotations.NotNull;
45
import org.junit.Test;
56
import org.rnorth.ducttape.RetryCountExceededException;
67
import org.testcontainers.containers.GenericContainer;
78
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
9+
import org.testcontainers.images.builder.ImageFromDockerfile;
810

911
import java.time.Duration;
1012
import java.util.HashMap;
@@ -200,7 +202,7 @@ public void testWaitUntilReadyWithSpecificPort() {
200202
}
201203

202204
@Test
203-
public void testWaitUntilReadyWithTimoutCausedByReadTimeout() {
205+
public void testWaitUntilReadyWithTimeoutCausedByReadTimeout() {
204206
try (
205207
GenericContainer<?> container = startContainerWithCommand(
206208
createShellCommand("0 Connection Refused", GOOD_RESPONSE_BODY, 9090),
@@ -212,6 +214,31 @@ public void testWaitUntilReadyWithTimoutCausedByReadTimeout() {
212214
}
213215
}
214216

217+
/**
218+
* Test to validate fix from GitHub Pull Request <a href="https://github.com/testcontainers/testcontainers-java/pull/5778">#5778</a>, i.e. when the container startup fails (ContainerLaunchException) before timeout for some reason, we are able to see the root cause of the error in the stack trace, e.g. in this case, a TLS certificate validation error during the TLS handshake test, because we are using a NGINX docker image with self-signed certificate created with the image, that is obviously not trusted.
219+
* The exceptions we should see in the stacktrace ('/' means 'caused by'): ContainerLaunchException / TimeoutException / RuntimeException / SSLHandshakeException / ValidatorException (in sun.* package so not accessible) / SunCertPathBuilderException (in sun.* package so not accessible).
220+
*/
221+
@Test
222+
public void testWaitUntilReadyWithTimeoutCausedBySslHandshakeError() {
223+
try (
224+
GenericContainer<?> container = new GenericContainer<>(
225+
new ImageFromDockerfile()
226+
.withFileFromClasspath("Dockerfile", "https-wait-strategy-dockerfile/Dockerfile")
227+
.withFileFromClasspath("nginx-ssl.conf", "https-wait-strategy-dockerfile/nginx-ssl.conf")
228+
)
229+
.withExposedPorts(8443)
230+
.waitingFor(
231+
createHttpWaitStrategy(ready)
232+
.forPort(8443)
233+
.usingTls()
234+
.withStartupTimeout(Duration.ofMillis(WAIT_TIMEOUT_MILLIS))
235+
)
236+
) {
237+
Throwable throwable = Assertions.catchThrowable(container::start);
238+
assertThat(throwable).hasStackTraceContaining("javax.net.ssl.SSLHandshakeException");
239+
}
240+
}
241+
215242
/**
216243
* @param ready the AtomicBoolean on which to indicate success
217244
* @return the WaitStrategy under test
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM nginx:1.17-alpine
2+
3+
# Create keypair and self-signed certificate for https test
4+
RUN apk update && apk add bash openssl && openssl req -batch -x509 -nodes -days 365 -newkey rsa:2048 -subj "/CN=localhost" -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
5+
6+
ADD nginx-ssl.conf /etc/nginx/conf.d/default.conf
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This configuration makes Nginx listen on port port 8443
2+
# In order to use this config, add this line to the Dockerfile to create the keypair and self-signed certificate:
3+
# RUN apk update && apk add openssl && openssl req -batch -x509 -nodes -days 365 -newkey rsa:2048 -subj "/CN=localhost" -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
4+
5+
server {
6+
listen 8443 ssl;
7+
server_name localhost;
8+
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
9+
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
10+
}

0 commit comments

Comments
 (0)