11package 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-
103import com .github .dockerjava .api .DockerClient ;
114import com .github .dockerjava .api .async .ResultCallback ;
125import com .github .dockerjava .api .command .PullImageResultCallback ;
6+ import com .github .dockerjava .api .exception .NotFoundException ;
137import 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 ;
198import org .intellij .lang .annotations .Language ;
209import org .junit .AfterClass ;
2110import org .junit .Before ;
2716import org .testcontainers .containers .ContainerState ;
2817import org .testcontainers .containers .DockerComposeContainer ;
2918import 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 ;
3122import 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