Skip to content

Commit 8b6776c

Browse files
authored
Allow to define a custom ImagePullPolicy via configuration (#7520)
Use `pull.policy` in configuration file.
1 parent c4d1240 commit 8b6776c

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

core/src/main/java/org/testcontainers/images/PullPolicy.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,64 @@
11
package org.testcontainers.images;
22

3+
import com.google.common.annotations.VisibleForTesting;
34
import lombok.experimental.UtilityClass;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.testcontainers.utility.TestcontainersConfiguration;
47

58
import java.time.Duration;
69

710
/**
811
* Convenience class with logic for building common {@link ImagePullPolicy} instances.
912
*
1013
*/
14+
@Slf4j
1115
@UtilityClass
1216
public class PullPolicy {
1317

18+
@VisibleForTesting
19+
static ImagePullPolicy instance;
20+
21+
@VisibleForTesting
22+
static ImagePullPolicy defaultImplementation = new DefaultPullPolicy();
23+
1424
/**
1525
* Convenience method for returning the {@link DefaultPullPolicy} default image pull policy
1626
* @return {@link ImagePullPolicy}
1727
*/
18-
public static ImagePullPolicy defaultPolicy() {
19-
return new DefaultPullPolicy();
28+
public static synchronized ImagePullPolicy defaultPolicy() {
29+
if (instance != null) {
30+
return instance;
31+
}
32+
33+
String imagePullPolicyClassName = TestcontainersConfiguration.getInstance().getImagePullPolicy();
34+
if (imagePullPolicyClassName != null) {
35+
log.debug("Attempting to instantiate an ImagePullPolicy with class: {}", imagePullPolicyClassName);
36+
ImagePullPolicy configuredInstance;
37+
try {
38+
configuredInstance =
39+
(ImagePullPolicy) Thread
40+
.currentThread()
41+
.getContextClassLoader()
42+
.loadClass(imagePullPolicyClassName)
43+
.getConstructor()
44+
.newInstance();
45+
} catch (Exception e) {
46+
throw new IllegalArgumentException(
47+
"Configured ImagePullPolicy could not be loaded: " + imagePullPolicyClassName,
48+
e
49+
);
50+
}
51+
52+
log.info("Found configured Image Pull Policy: {}", configuredInstance.getClass());
53+
54+
instance = configuredInstance;
55+
} else {
56+
instance = defaultImplementation;
57+
}
58+
59+
log.info("Image pull policy will be performed by: {}", instance);
60+
61+
return instance;
2062
}
2163

2264
/**

core/src/main/java/org/testcontainers/images/RemoteDockerImage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class RemoteDockerImage extends LazyFuture<String> {
3535
private Future<DockerImageName> imageNameFuture;
3636

3737
@With
38-
private ImagePullPolicy imagePullPolicy = PullPolicy.defaultPolicy();
38+
ImagePullPolicy imagePullPolicy = PullPolicy.defaultPolicy();
3939

4040
@With
4141
private ImageNameSubstitutor imageNameSubstitutor = ImageNameSubstitutor.instance();

core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ public String getImageSubstitutorClassName() {
213213
return getEnvVarOrProperty("image.substitutor", null);
214214
}
215215

216+
public String getImagePullPolicy() {
217+
return getEnvVarOrProperty("pull.policy", null);
218+
}
219+
216220
public Integer getClientPingTimeout() {
217221
return Integer.parseInt(getEnvVarOrProperty("client.ping.timeout", "10"));
218222
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.testcontainers.images;
2+
3+
import org.junit.After;
4+
import org.junit.Before;
5+
import org.junit.Rule;
6+
import org.junit.Test;
7+
import org.mockito.Mockito;
8+
import org.testcontainers.DockerRegistryContainer;
9+
import org.testcontainers.containers.GenericContainer;
10+
import org.testcontainers.utility.FakeImagePullPolicy;
11+
import org.testcontainers.utility.MockTestcontainersConfigurationRule;
12+
import org.testcontainers.utility.TestcontainersConfiguration;
13+
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
16+
public class OverrideImagePullPolicyTest {
17+
18+
@Rule
19+
public MockTestcontainersConfigurationRule config = new MockTestcontainersConfigurationRule();
20+
21+
private ImagePullPolicy originalInstance;
22+
23+
private ImagePullPolicy originalDefaultImplementation;
24+
25+
@Before
26+
public void setUp() {
27+
this.originalInstance = PullPolicy.instance;
28+
this.originalDefaultImplementation = PullPolicy.defaultImplementation;
29+
PullPolicy.instance = null;
30+
PullPolicy.defaultImplementation = Mockito.mock(ImagePullPolicy.class);
31+
}
32+
33+
@After
34+
public void tearDown() {
35+
PullPolicy.instance = originalInstance;
36+
PullPolicy.defaultImplementation = originalDefaultImplementation;
37+
}
38+
39+
@Test
40+
public void simpleConfigurationTest() {
41+
Mockito
42+
.doReturn(FakeImagePullPolicy.class.getCanonicalName())
43+
.when(TestcontainersConfiguration.getInstance())
44+
.getImagePullPolicy();
45+
46+
try (DockerRegistryContainer registry = new DockerRegistryContainer()) {
47+
registry.start();
48+
GenericContainer<?> container = new GenericContainer<>(registry.createImage()).withExposedPorts(8080);
49+
container.start();
50+
assertThat(container.getImage().imagePullPolicy).isInstanceOf(FakeImagePullPolicy.class);
51+
container.stop();
52+
}
53+
}
54+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.testcontainers.utility;
2+
3+
import org.testcontainers.images.AbstractImagePullPolicy;
4+
import org.testcontainers.images.ImageData;
5+
6+
public class FakeImagePullPolicy extends AbstractImagePullPolicy {
7+
8+
@Override
9+
protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) {
10+
return false;
11+
}
12+
}

docs/features/advanced_options.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ It is possible to specify an Image Pull Policy to determine at runtime whether a
3131
[Custom image pull policy](../../core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java) inside_block:custom_image_pull_policy
3232
<!--/codeinclude-->
3333

34+
You can also configure Testcontainers to use your custom implementation by using `pull.policy`
35+
36+
=== "`src/test/resources/testcontainers.properties`"
37+
```text
38+
pull.policy=com.mycompany.testcontainers.ExampleImagePullPolicy
39+
```
40+
41+
Please see [the documentation on configuration mechanisms](./configuration.md) for more information.
42+
3443
## Customizing the container
3544

3645
### Using docker-java

0 commit comments

Comments
 (0)