Skip to content

Commit e69a9ce

Browse files
committed
Normalize image names in prefix substitutor
Optionally normalize docker image names to use `library/` prefix when they don't have any namespace at all. This allows for the `PrefixingImageNameSubstitutor` to be used to redirect Docker Hub requests to a private registry without having to apply otherwise redundant changes to the test code.
1 parent 8db891a commit e69a9ce

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public final class DockerImageName {
2626

2727
private static final Pattern REPO_NAME = Pattern.compile(REPO_NAME_PART + "(/" + REPO_NAME_PART + ")*");
2828

29-
private static final String LIBRARY_PREFIX = "library/";
29+
static final String LIBRARY_PREFIX = "library/";
3030

3131
private final String rawName;
3232

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

+23-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ final class PrefixingImageNameSubstitutor extends ImageNameSubstitutor {
1616
@VisibleForTesting
1717
static final String PREFIX_PROPERTY_KEY = "hub.image.name.prefix";
1818

19+
@VisibleForTesting
20+
static final String NORMALIZE_PROPERTY_KEY = "hub.image.name.normalize";
21+
1922
private TestcontainersConfiguration configuration = TestcontainersConfiguration.getInstance();
2023

2124
@VisibleForTesting
@@ -26,6 +29,9 @@ final class PrefixingImageNameSubstitutor extends ImageNameSubstitutor {
2629
@Override
2730
public DockerImageName apply(DockerImageName original) {
2831
final String configuredPrefix = configuration.getEnvVarOrProperty(PREFIX_PROPERTY_KEY, "");
32+
final boolean normalize = Boolean.parseBoolean(
33+
configuration.getEnvVarOrProperty(NORMALIZE_PROPERTY_KEY, "false")
34+
);
2935

3036
if (configuredPrefix.isEmpty()) {
3137
log.debug("No prefix is configured");
@@ -38,13 +44,27 @@ public DockerImageName apply(DockerImageName original) {
3844
return original;
3945
}
4046

41-
log.debug("Applying changes to image name {}: applying prefix '{}'", original, configuredPrefix);
47+
log.debug(
48+
"Applying changes to image name {}: applying prefix '{}' with normalization: {}",
49+
original,
50+
configuredPrefix,
51+
normalize
52+
);
4253

4354
DockerImageName prefixAsImage = DockerImageName.parse(configuredPrefix);
4455

45-
return original
56+
String repository = original.getRepository();
57+
if (normalize && !repository.contains("/")) {
58+
repository = DockerImageName.LIBRARY_PREFIX + repository;
59+
}
60+
61+
DockerImageName substituted = original
4662
.withRegistry(prefixAsImage.getRegistry())
47-
.withRepository(prefixAsImage.getRepository() + original.getRepository());
63+
.withRepository(prefixAsImage.getRepository() + repository);
64+
if (normalize) {
65+
substituted = substituted.asCompatibleSubstituteFor(original);
66+
}
67+
return substituted;
4868
}
4969

5070
@Override

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

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ public void testHappyPath() {
3333
.isEqualTo("someregistry.com/our-mirror/some/image:tag");
3434
}
3535

36+
@Test
37+
public void testNormalizeToLibraryPath() {
38+
when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any()))
39+
.thenReturn("someregistry.com/our-mirror/");
40+
when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.NORMALIZE_PROPERTY_KEY), any()))
41+
.thenReturn("true");
42+
43+
final DockerImageName result = underTest.apply(DockerImageName.parse("image:tag"));
44+
45+
assertThat(result.asCanonicalNameString())
46+
.as("The prefix is applied")
47+
.isEqualTo("someregistry.com/our-mirror/library/image:tag");
48+
result.assertCompatibleWith(DockerImageName.parse("image:tag"));
49+
}
50+
3651
@Test
3752
public void hubIoRegistryIsNotChanged() {
3853
when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any()))

docs/features/image_name_substitution.md

+7
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ Testcontainers will not apply the prefix to:
7777
* non-Hub image names (e.g. where another registry is set)
7878
* Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a `docker.io` or `registry.hub.docker.com` host part)
7979

80+
If you want your registry to handle both official Docker Hub images (e.g `postgres`)
81+
as well as images from other registries (e.g `mycompany/postgres`), you can use the
82+
`TESTCONTAINERS_HUB_IMAGE_NAME_NORMALIZE` environment variable or the `hub.image.name.normalize`
83+
configuration option. When set to `true`, Testcontainers will normalize the official Docker Hub
84+
image names to start with `library/`. When this option is used, Testcontainers will additionally
85+
disable image compatibility checks done by some containers, so it the compatibility responsibility
86+
is on the user.
8087

8188

8289
## Developing a custom function for transforming image names on the fly

0 commit comments

Comments
 (0)