Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to define a custom ImagePullPolicy via configuration #7520

Merged
merged 9 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions core/src/main/java/org/testcontainers/images/PullPolicy.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,64 @@
package org.testcontainers.images;

import com.google.common.annotations.VisibleForTesting;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.testcontainers.utility.TestcontainersConfiguration;

import java.time.Duration;

/**
* Convenience class with logic for building common {@link ImagePullPolicy} instances.
*
*/
@Slf4j
@UtilityClass
public class PullPolicy {

@VisibleForTesting
static ImagePullPolicy instance;

@VisibleForTesting
static ImagePullPolicy defaultImplementation = new DefaultPullPolicy();

/**
* Convenience method for returning the {@link DefaultPullPolicy} default image pull policy
* @return {@link ImagePullPolicy}
*/
public static ImagePullPolicy defaultPolicy() {
return new DefaultPullPolicy();
public static synchronized ImagePullPolicy defaultPolicy() {
if (instance != null) {
return instance;
}

String imagePullPolicyClassName = TestcontainersConfiguration.getInstance().getImagePullPolicy();
if (imagePullPolicyClassName != null) {
log.debug("Attempting to instantiate an ImagePullPolicy with class: {}", imagePullPolicyClassName);
ImagePullPolicy configuredInstance;
try {
configuredInstance =
(ImagePullPolicy) Thread
.currentThread()
.getContextClassLoader()
.loadClass(imagePullPolicyClassName)
.getConstructor()
.newInstance();
} catch (Exception e) {
throw new IllegalArgumentException(
"Configured ImagePullPolicy could not be loaded: " + imagePullPolicyClassName,
e
);
}

log.info("Found configured Image Pull Policy: {}", configuredInstance.getClass());

instance = configuredInstance;
} else {
instance = defaultImplementation;
}

log.info("Image pull policy will be performed by: {}", instance);

return instance;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class RemoteDockerImage extends LazyFuture<String> {
private Future<DockerImageName> imageNameFuture;

@With
private ImagePullPolicy imagePullPolicy = PullPolicy.defaultPolicy();
ImagePullPolicy imagePullPolicy = PullPolicy.defaultPolicy();

@With
private ImageNameSubstitutor imageNameSubstitutor = ImageNameSubstitutor.instance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ public String getImageSubstitutorClassName() {
return getEnvVarOrProperty("image.substitutor", null);
}

public String getImagePullPolicy() {
return getEnvVarOrProperty("pull.policy", null);
}

public Integer getClientPingTimeout() {
return Integer.parseInt(getEnvVarOrProperty("client.ping.timeout", "10"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.testcontainers.images;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
import org.testcontainers.DockerRegistryContainer;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.FakeImagePullPolicy;
import org.testcontainers.utility.MockTestcontainersConfigurationRule;
import org.testcontainers.utility.TestcontainersConfiguration;

import static org.assertj.core.api.Assertions.assertThat;

public class OverrideImagePullPolicyTest {

@Rule
public MockTestcontainersConfigurationRule config = new MockTestcontainersConfigurationRule();

private ImagePullPolicy originalInstance;

private ImagePullPolicy originalDefaultImplementation;

@Before
public void setUp() {
this.originalInstance = PullPolicy.instance;
this.originalDefaultImplementation = PullPolicy.defaultImplementation;
PullPolicy.instance = null;
PullPolicy.defaultImplementation = Mockito.mock(ImagePullPolicy.class);
}

@After
public void tearDown() {
PullPolicy.instance = originalInstance;
PullPolicy.defaultImplementation = originalDefaultImplementation;
}

@Test
public void simpleConfigurationTest() {
Mockito
.doReturn(FakeImagePullPolicy.class.getCanonicalName())
.when(TestcontainersConfiguration.getInstance())
.getImagePullPolicy();

try (DockerRegistryContainer registry = new DockerRegistryContainer()) {
registry.start();
GenericContainer<?> container = new GenericContainer<>(registry.createImage()).withExposedPorts(8080);
container.start();
assertThat(container.getImage().imagePullPolicy).isInstanceOf(FakeImagePullPolicy.class);
container.stop();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.testcontainers.utility;

import org.testcontainers.images.AbstractImagePullPolicy;
import org.testcontainers.images.ImageData;

public class FakeImagePullPolicy extends AbstractImagePullPolicy {

@Override
protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) {
return false;
}
}
9 changes: 9 additions & 0 deletions docs/features/advanced_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ It is possible to specify an Image Pull Policy to determine at runtime whether a
[Custom image pull policy](../../core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java) inside_block:custom_image_pull_policy
<!--/codeinclude-->

You can also configure Testcontainers to use your custom implementation by using `pull.policy`

=== "`src/test/resources/testcontainers.properties`"
```text
pull.policy=com.mycompany.testcontainers.ExampleImagePullPolicy
```

Please see [the documentation on configuration mechanisms](./configuration.md) for more information.

## Customizing the container

### Using docker-java
Expand Down
Loading