Skip to content

Commit 3740f65

Browse files
authored
Fix AuthenticatedImagePullTest (#4560)
Previous implementation was assuming that Docker can pull from the gateway, which may not always be the case. This change makes the temporary registry run with host network, so that Docker can always pull from it.
1 parent aa273b5 commit 3740f65

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

core/src/test/java/org/testcontainers/utility/AuthenticatedImagePullTest.java

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
package org.testcontainers.utility;
22

3-
import static org.mockito.ArgumentMatchers.any;
4-
import static org.mockito.ArgumentMatchers.eq;
5-
import static org.mockito.Mockito.when;
6-
import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue;
7-
import static org.testcontainers.TestImages.DOCKER_REGISTRY_IMAGE;
8-
import static org.testcontainers.TestImages.TINY_IMAGE;
9-
103
import com.github.dockerjava.api.DockerClient;
114
import com.github.dockerjava.api.async.ResultCallback;
125
import com.github.dockerjava.api.command.PullImageResultCallback;
6+
import com.github.dockerjava.api.exception.NotFoundException;
137
import com.github.dockerjava.api.model.AuthConfig;
14-
import java.io.IOException;
15-
import java.nio.file.Files;
16-
import java.nio.file.Path;
17-
import java.nio.file.Paths;
18-
import java.util.concurrent.TimeUnit;
198
import org.intellij.lang.annotations.Language;
209
import org.junit.AfterClass;
2110
import org.junit.Before;
@@ -27,9 +16,27 @@
2716
import org.testcontainers.containers.ContainerState;
2817
import org.testcontainers.containers.DockerComposeContainer;
2918
import org.testcontainers.containers.GenericContainer;
30-
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
19+
import org.testcontainers.containers.output.FrameConsumerResultCallback;
20+
import org.testcontainers.containers.output.OutputFrame;
21+
import org.testcontainers.containers.output.WaitingConsumer;
3122
import org.testcontainers.images.builder.ImageFromDockerfile;
3223

24+
import java.io.IOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.nio.file.Paths;
28+
import java.util.concurrent.TimeUnit;
29+
import java.util.concurrent.atomic.AtomicInteger;
30+
import java.util.regex.Matcher;
31+
import java.util.regex.Pattern;
32+
33+
import static org.mockito.ArgumentMatchers.any;
34+
import static org.mockito.ArgumentMatchers.eq;
35+
import static org.mockito.Mockito.when;
36+
import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue;
37+
import static org.testcontainers.TestImages.DOCKER_REGISTRY_IMAGE;
38+
import static org.testcontainers.TestImages.TINY_IMAGE;
39+
3340
/**
3441
* This test checks the integration between Testcontainers and an authenticated registry, but uses
3542
* a mock instance of {@link RegistryAuthLocator} - the purpose of the test is solely to ensure that
@@ -52,8 +59,10 @@ public class AuthenticatedImagePullTest {
5259
.env("REGISTRY_AUTH_HTPASSWD_PATH", "/htpasswd")
5360
.env("REGISTRY_AUTH_HTPASSWD_REALM", "Test");
5461
}))
55-
.withExposedPorts(5000)
56-
.waitingFor(new HttpWaitStrategy());
62+
.withEnv("REGISTRY_HTTP_ADDR", "127.0.0.1:0")
63+
.withCreateContainerCmdModifier(cmd -> {
64+
cmd.getHostConfig().withNetworkMode("host");
65+
});
5766

5867
private static RegistryAuthLocator originalAuthLocatorSingleton;
5968
private static DockerClient client;
@@ -62,11 +71,34 @@ public class AuthenticatedImagePullTest {
6271
private static RegistryAuthLocator mockAuthLocator;
6372

6473
@BeforeClass
65-
public static void setUp() throws InterruptedException {
74+
public static void setUp() throws Exception {
6675
originalAuthLocatorSingleton = RegistryAuthLocator.instance();
6776
client = DockerClientFactory.instance().client();
6877

69-
String testRegistryAddress = authenticatedRegistry.getHost() + ":" + authenticatedRegistry.getFirstMappedPort();
78+
AtomicInteger port = new AtomicInteger(-1);
79+
try (FrameConsumerResultCallback resultCallback = new FrameConsumerResultCallback()) {
80+
WaitingConsumer waitingConsumer = new WaitingConsumer();
81+
resultCallback.addConsumer(OutputFrame.OutputType.STDERR, waitingConsumer);
82+
83+
client.logContainerCmd(authenticatedRegistry.getContainerId())
84+
.withStdErr(true)
85+
.withFollowStream(true)
86+
.exec(resultCallback);
87+
88+
Pattern pattern = Pattern.compile(".*listening on .*:(\\d+).*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
89+
waitingConsumer.waitUntil(it -> {
90+
String s = it.getUtf8String();
91+
Matcher matcher = pattern.matcher(s);
92+
if (matcher.matches()) {
93+
port.set(Integer.parseInt(matcher.group(1)));
94+
return true;
95+
} else {
96+
return false;
97+
}
98+
}, 10, TimeUnit.SECONDS);
99+
}
100+
101+
String testRegistryAddress = authenticatedRegistry.getHost() + ":" + port.get();
70102
testImageName = testRegistryAddress + "/alpine";
71103

72104
final DockerImageName expectedName = DockerImageName.parse(testImageName);
@@ -88,7 +120,11 @@ public static void setUp() throws InterruptedException {
88120
@Before
89121
public void removeImageFromLocalDocker() {
90122
// remove the image tag from local docker so that it must be pulled before use
91-
client.removeImageCmd(testImageName).withForce(true).exec();
123+
try {
124+
client.removeImageCmd(testImageName).withForce(true).exec();
125+
} catch (NotFoundException ignored) {
126+
127+
}
92128
}
93129

94130
@AfterClass

0 commit comments

Comments
 (0)