diff --git a/core/src/main/java/org/testcontainers/utility/DockerImageName.java b/core/src/main/java/org/testcontainers/utility/DockerImageName.java index e3a35855bf8..a1b956429b7 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerImageName.java +++ b/core/src/main/java/org/testcontainers/utility/DockerImageName.java @@ -26,7 +26,7 @@ public final class DockerImageName { private static final Pattern REPO_NAME = Pattern.compile(REPO_NAME_PART + "(/" + REPO_NAME_PART + ")*"); - private static final String LIBRARY_PREFIX = "library/"; + static final String LIBRARY_PREFIX = "library/"; private final String rawName; diff --git a/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java b/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java index 7cf082000a4..0783e201168 100644 --- a/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java +++ b/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java @@ -16,6 +16,9 @@ final class PrefixingImageNameSubstitutor extends ImageNameSubstitutor { @VisibleForTesting static final String PREFIX_PROPERTY_KEY = "hub.image.name.prefix"; + @VisibleForTesting + static final String NORMALIZE_PROPERTY_KEY = "hub.image.name.normalize"; + private TestcontainersConfiguration configuration = TestcontainersConfiguration.getInstance(); @VisibleForTesting @@ -26,6 +29,9 @@ final class PrefixingImageNameSubstitutor extends ImageNameSubstitutor { @Override public DockerImageName apply(DockerImageName original) { final String configuredPrefix = configuration.getEnvVarOrProperty(PREFIX_PROPERTY_KEY, ""); + final boolean normalize = Boolean.parseBoolean( + configuration.getEnvVarOrProperty(NORMALIZE_PROPERTY_KEY, "false") + ); if (configuredPrefix.isEmpty()) { log.debug("No prefix is configured"); @@ -38,13 +44,27 @@ public DockerImageName apply(DockerImageName original) { return original; } - log.debug("Applying changes to image name {}: applying prefix '{}'", original, configuredPrefix); + log.debug( + "Applying changes to image name {}: applying prefix '{}' with normalization: {}", + original, + configuredPrefix, + normalize + ); DockerImageName prefixAsImage = DockerImageName.parse(configuredPrefix); - return original + String repository = original.getRepository(); + if (normalize && !repository.contains("/")) { + repository = DockerImageName.LIBRARY_PREFIX + repository; + } + + DockerImageName substituted = original .withRegistry(prefixAsImage.getRegistry()) - .withRepository(prefixAsImage.getRepository() + original.getRepository()); + .withRepository(prefixAsImage.getRepository() + repository); + if (normalize) { + substituted = substituted.asCompatibleSubstituteFor(original); + } + return substituted; } @Override diff --git a/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java b/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java index 04786119e36..3d336b5afd9 100644 --- a/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java +++ b/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java @@ -33,6 +33,21 @@ public void testHappyPath() { .isEqualTo("someregistry.com/our-mirror/some/image:tag"); } + @Test + public void testNormalizeToLibraryPath() { + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.NORMALIZE_PROPERTY_KEY), any())) + .thenReturn("true"); + + final DockerImageName result = underTest.apply(DockerImageName.parse("image:tag")); + + assertThat(result.asCanonicalNameString()) + .as("The prefix is applied") + .isEqualTo("someregistry.com/our-mirror/library/image:tag"); + result.assertCompatibleWith(DockerImageName.parse("image:tag")); + } + @Test public void hubIoRegistryIsNotChanged() { when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) diff --git a/docs/features/image_name_substitution.md b/docs/features/image_name_substitution.md index cf2b09d3d8e..bb777c40266 100644 --- a/docs/features/image_name_substitution.md +++ b/docs/features/image_name_substitution.md @@ -77,6 +77,13 @@ Testcontainers will not apply the prefix to: * non-Hub image names (e.g. where another registry is set) * 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) +If you want your registry to handle both official Docker Hub images (e.g `postgres`) +as well as images from other registries (e.g `mycompany/postgres`), you can use the +`TESTCONTAINERS_HUB_IMAGE_NAME_NORMALIZE` environment variable or the `hub.image.name.normalize` +configuration option. When set to `true`, Testcontainers will normalize the official Docker Hub +image names to start with `library/`. When this option is used, Testcontainers will additionally +disable image compatibility checks done by some containers, so it the compatibility responsibility +is on the user. ## Developing a custom function for transforming image names on the fly