Skip to content

Commit aad5fed

Browse files
Fix false positive in DockerImageName.isCompatibleWith for library/-prefixed images
1 parent deb78e1 commit aad5fed

2 files changed

Lines changed: 61 additions & 8 deletions

File tree

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,13 @@ public DockerImageName asCompatibleSubstituteFor(DockerImageName otherImageName)
233233
* @return whether this image has declared compatibility.
234234
*/
235235
public boolean isCompatibleWith(DockerImageName other) {
236-
// Make sure we always compare against a version of the image name containing the LIBRARY_PREFIX
237-
String finalImageName;
238-
if (this.repository.startsWith(LIBRARY_PREFIX)) {
239-
finalImageName = this.repository;
240-
} else {
241-
finalImageName = LIBRARY_PREFIX + this.repository;
236+
if (other.equals(this)) {
237+
return true;
242238
}
243-
DockerImageName imageWithLibraryPrefix = DockerImageName.parse(finalImageName);
244-
if (other.equals(this) || imageWithLibraryPrefix.equals(this)) {
239+
240+
// 'library/foo' and 'foo' refer to the same official Docker Hub image, so compare both
241+
// names normalized to include the LIBRARY_PREFIX.
242+
if (withLibraryPrefix(other).equals(withLibraryPrefix(this))) {
245243
return true;
246244
}
247245

@@ -252,6 +250,13 @@ public boolean isCompatibleWith(DockerImageName other) {
252250
return this.compatibleSubstituteFor.isCompatibleWith(other);
253251
}
254252

253+
private static DockerImageName withLibraryPrefix(DockerImageName image) {
254+
if (!image.registry.isEmpty() || image.repository.startsWith(LIBRARY_PREFIX)) {
255+
return image;
256+
}
257+
return image.withRepository(LIBRARY_PREFIX + image.repository);
258+
}
259+
255260
/**
256261
* Behaves as {@link DockerImageName#isCompatibleWith(DockerImageName)} but throws an exception
257262
* rather than returning false if a mismatch is detected.

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,54 @@ void testAssertMethodAcceptsCompatibleLibraryPrefix() {
9797
subject.assertCompatibleWith(DockerImageName.parse("foo"));
9898
}
9999

100+
@Test
101+
void testLibraryPrefixedImageIsNotCompatibleWithDifferentImage() {
102+
DockerImageName subject = DockerImageName.parse("library/foo:1.2.3");
103+
104+
assertThat(subject.isCompatibleWith(DockerImageName.parse("bar"))).as("library/foo:1.2.3 != bar").isFalse();
105+
assertThat(subject.isCompatibleWith(DockerImageName.parse("repo/bar")))
106+
.as("library/foo:1.2.3 != repo/bar")
107+
.isFalse();
108+
assertThat(subject.isCompatibleWith(DockerImageName.parse("library/bar")))
109+
.as("library/foo:1.2.3 != library/bar")
110+
.isFalse();
111+
}
112+
113+
@Test
114+
void testLibraryPrefixIsInterchangeable() {
115+
assertThat(DockerImageName.parse("library/foo").isCompatibleWith(DockerImageName.parse("foo")))
116+
.as("library/foo ~= foo")
117+
.isTrue();
118+
assertThat(DockerImageName.parse("foo").isCompatibleWith(DockerImageName.parse("library/foo")))
119+
.as("foo ~= library/foo")
120+
.isTrue();
121+
assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo")))
122+
.as("library/foo:1.2.3 ~= foo")
123+
.isTrue();
124+
assertThat(DockerImageName.parse("foo:1.2.3").isCompatibleWith(DockerImageName.parse("library/foo")))
125+
.as("foo:1.2.3 ~= library/foo")
126+
.isTrue();
127+
assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo:1.2.3")))
128+
.as("library/foo:1.2.3 ~= foo:1.2.3")
129+
.isTrue();
130+
assertThat(DockerImageName.parse("library/foo:1.2.3").isCompatibleWith(DockerImageName.parse("foo:4.5.6")))
131+
.as("library/foo:1.2.3 != foo:4.5.6")
132+
.isFalse();
133+
assertThat(DockerImageName.parse("some.registry/foo").isCompatibleWith(DockerImageName.parse("library/foo")))
134+
.as("some.registry/foo != library/foo")
135+
.isFalse();
136+
}
137+
138+
@Test
139+
void testLibraryPrefixedImageWithClaimedCompatibility() {
140+
DockerImageName subject = DockerImageName.parse("library/foo:1.2.3").asCompatibleSubstituteFor("bar");
141+
142+
assertThat(subject.isCompatibleWith(DockerImageName.parse("bar"))).as("library/foo:1.2.3(bar) ~= bar").isTrue();
143+
assertThat(subject.isCompatibleWith(DockerImageName.parse("fizz")))
144+
.as("library/foo:1.2.3(bar) != fizz")
145+
.isFalse();
146+
}
147+
100148
@Test
101149
void testAssertMethodRejectsIncompatible() {
102150
DockerImageName subject = DockerImageName.parse("foo");

0 commit comments

Comments
 (0)