Skip to content

Commit 02782d9

Browse files
authored
Replace deprecated checkAndPullImage with RemoteDockerImage (#5148)
* Replace deprecated `checkAndPullImage` with `RemoteDockerImage` * fix `runCommandInsideDockerShouldNotFailIfImageDoesNotExistsLocally` * Remove `LoggerFactory` usage * avoid name substitution in `DockerComposeContainer`/`ImageFromDockerfile` * fix `AuthenticatedImagePullTest` * remove accidential `@Ignore` * fix indentation * put `clearCache` after `catch()`
1 parent 6414df1 commit 02782d9

File tree

11 files changed

+70
-32
lines changed

11 files changed

+70
-32
lines changed

core/src/main/java/org/testcontainers/DockerClientFactory.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
import org.testcontainers.dockerclient.DockerClientProviderStrategy;
2626
import org.testcontainers.dockerclient.DockerMachineClientProviderStrategy;
2727
import org.testcontainers.dockerclient.TransportConfig;
28+
import org.testcontainers.images.RemoteDockerImage;
2829
import org.testcontainers.images.TimeLimitedLoggedPullImageResultCallback;
2930
import org.testcontainers.utility.ComparableVersion;
3031
import org.testcontainers.utility.DockerImageName;
31-
import org.testcontainers.utility.ImageNameSubstitutor;
3232
import org.testcontainers.utility.MountableFile;
3333
import org.testcontainers.utility.ResourceReaper;
3434
import org.testcontainers.utility.RyukResourceReaper;
@@ -236,7 +236,6 @@ public void close() {
236236
checkDiskSpace(client, ryukContainerId);
237237
} else {
238238
runInsideDocker(
239-
client,
240239
createContainerCmd -> {
241240
createContainerCmd.withName("testcontainers-checks-" + SESSION_ID);
242241
createContainerCmd.getHostConfig().withAutoRemove(true);
@@ -335,9 +334,12 @@ private boolean checkMountableFile() {
335334
}
336335

337336
/**
338-
* Check whether the image is available locally and pull it otherwise
339-
*/
337+
* Check whether the image is available locally and pull it otherwise
338+
*
339+
* @deprecated use {@link RemoteDockerImage}
340+
*/
340341
@SneakyThrows
342+
@Deprecated
341343
public void checkAndPullImage(DockerClient client, String image) {
342344
try {
343345
client.inspectImageCmd(image).exec();
@@ -363,18 +365,14 @@ public String dockerHostIpAddress() {
363365
}
364366

365367
public <T> T runInsideDocker(Consumer<CreateContainerCmd> createContainerCmdConsumer, BiFunction<DockerClient, String, T> block) {
366-
// We can't use client() here because it might create an infinite loop
367-
return runInsideDocker(getOrInitializeStrategy().getDockerClient(), createContainerCmdConsumer, block);
368+
return runInsideDocker(TINY_IMAGE, createContainerCmdConsumer, block);
368369
}
369370

370-
private <T> T runInsideDocker(DockerClient client, Consumer<CreateContainerCmd> createContainerCmdConsumer, BiFunction<DockerClient, String, T> block) {
371-
372-
final String tinyImage = ImageNameSubstitutor.instance().apply(TINY_IMAGE).asCanonicalNameString();
373-
374-
checkAndPullImage(client, tinyImage);
371+
<T> T runInsideDocker(DockerImageName imageName, Consumer<CreateContainerCmd> createContainerCmdConsumer, BiFunction<DockerClient, String, T> block) {
372+
RemoteDockerImage dockerImage = new RemoteDockerImage(imageName);
375373
HashMap<String, String> labels = new HashMap<>(DEFAULT_LABELS);
376374
labels.putAll(ResourceReaper.instance().getLabels());
377-
CreateContainerCmd createContainerCmd = client.createContainerCmd(tinyImage)
375+
CreateContainerCmd createContainerCmd = client.createContainerCmd(dockerImage.get())
378376
.withLabels(labels);
379377
createContainerCmdConsumer.accept(createContainerCmd);
380378
String id = createContainerCmd.exec().getId();

core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
2626
import org.testcontainers.containers.wait.strategy.WaitStrategy;
2727
import org.testcontainers.dockerclient.TransportConfig;
28+
import org.testcontainers.images.RemoteDockerImage;
2829
import org.testcontainers.lifecycle.Startable;
2930
import org.testcontainers.utility.AuditLogger;
3031
import org.testcontainers.utility.Base58;
3132
import org.testcontainers.utility.CommandLine;
3233
import org.testcontainers.utility.DockerImageName;
3334
import org.testcontainers.utility.DockerLoggerFactory;
35+
import org.testcontainers.utility.ImageNameSubstitutor;
3436
import org.testcontainers.utility.LogUtils;
3537
import org.testcontainers.utility.MountableFile;
3638
import org.testcontainers.utility.PathUtils;
@@ -186,7 +188,9 @@ private void pullImages() {
186188
.forEach(imageName -> {
187189
try {
188190
log.info("Preemptively checking local images for '{}', referenced via a compose file or transitive Dockerfile. If not available, it will be pulled.", imageName);
189-
DockerClientFactory.instance().checkAndPullImage(dockerClient, imageName);
191+
new RemoteDockerImage(DockerImageName.parse(imageName))
192+
.withImageNameSubstitutor(ImageNameSubstitutor.noop())
193+
.get();
190194
} catch (Exception e) {
191195
log.warn("Unable to pre-fetch an image ({}) depended upon by Docker Compose build - startup will continue but may fail. Exception message was: {}", imageName, e.getMessage());
192196
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
enum LocalImagesCache {
2222
INSTANCE;
2323

24-
private final AtomicBoolean initialized = new AtomicBoolean(false);
24+
@VisibleForTesting
25+
final AtomicBoolean initialized = new AtomicBoolean(false);
2526

2627
@VisibleForTesting
2728
final Map<DockerImageName, ImageData> cache = new ConcurrentHashMap<>();

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import lombok.NonNull;
1111
import lombok.SneakyThrows;
1212
import lombok.ToString;
13-
import lombok.experimental.Wither;
13+
import lombok.With;
1414
import org.slf4j.Logger;
1515
import org.testcontainers.DockerClientFactory;
1616
import org.testcontainers.containers.ContainerFetchException;
@@ -34,9 +34,12 @@ public class RemoteDockerImage extends LazyFuture<String> {
3434
@ToString.Exclude
3535
private Future<DockerImageName> imageNameFuture;
3636

37-
@Wither
37+
@With
3838
private ImagePullPolicy imagePullPolicy = PullPolicy.defaultPolicy();
3939

40+
@With
41+
private ImageNameSubstitutor imageNameSubstitutor = ImageNameSubstitutor.instance();
42+
4043
@ToString.Exclude
4144
private DockerClient dockerClient = DockerClientFactory.lazyClient();
4245

@@ -115,7 +118,7 @@ private DockerImageName getImageName() throws InterruptedException, ExecutionExc
115118
final DockerImageName specifiedImageName = imageNameFuture.get();
116119

117120
// Allow the image name to be substituted
118-
return ImageNameSubstitutor.instance().apply(specifiedImageName);
121+
return imageNameSubstitutor.apply(specifiedImageName);
119122
}
120123

121124
@ToString.Include(name = "imageName", rank = 1)

core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
import org.slf4j.Logger;
1414
import org.testcontainers.DockerClientFactory;
1515
import org.testcontainers.images.ParsedDockerfile;
16+
import org.testcontainers.images.RemoteDockerImage;
1617
import org.testcontainers.images.builder.traits.BuildContextBuilderTrait;
1718
import org.testcontainers.images.builder.traits.ClasspathTrait;
1819
import org.testcontainers.images.builder.traits.DockerfileTrait;
1920
import org.testcontainers.images.builder.traits.FilesTrait;
2021
import org.testcontainers.images.builder.traits.StringsTrait;
2122
import org.testcontainers.utility.Base58;
23+
import org.testcontainers.utility.DockerImageName;
2224
import org.testcontainers.utility.DockerLoggerFactory;
25+
import org.testcontainers.utility.ImageNameSubstitutor;
2326
import org.testcontainers.utility.LazyFuture;
2427
import org.testcontainers.utility.ResourceReaper;
2528

@@ -172,7 +175,9 @@ private void prePullDependencyImages(Set<String> imagesToPull) {
172175
imagesToPull.forEach(imageName -> {
173176
try {
174177
log.info("Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.", imageName);
175-
DockerClientFactory.instance().checkAndPullImage(dockerClient, imageName);
178+
new RemoteDockerImage(DockerImageName.parse(imageName))
179+
.withImageNameSubstitutor(ImageNameSubstitutor.noop())
180+
.get();
176181
} catch (Exception e) {
177182
log.warn("Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}", imageName, e.getMessage());
178183
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public synchronized static ImageNameSubstitutor instance() {
5353
return instance;
5454
}
5555

56+
public static ImageNameSubstitutor noop() {
57+
return new NoopImageNameSubstitutor();
58+
}
59+
5660
private static ImageNameSubstitutor wrapWithLogging(final ImageNameSubstitutor wrappedInstance) {
5761
return new LogWrappedImageNameSubstitutor(wrappedInstance);
5862
}
@@ -127,4 +131,17 @@ protected String getDescription() {
127131
);
128132
}
129133
}
134+
135+
private static class NoopImageNameSubstitutor extends ImageNameSubstitutor {
136+
137+
@Override
138+
public DockerImageName apply(DockerImageName original) {
139+
return original;
140+
}
141+
142+
@Override
143+
protected String getDescription() {
144+
return "No-op substitutor";
145+
}
146+
}
130147
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.rnorth.ducttape.ratelimits.RateLimiterBuilder;
1818
import org.testcontainers.DockerClientFactory;
1919
import org.testcontainers.containers.ContainerState;
20+
import org.testcontainers.images.RemoteDockerImage;
2021

2122
import java.io.IOException;
2223
import java.net.InetSocketAddress;
@@ -85,16 +86,13 @@ private synchronized void maybeStart() {
8586
return;
8687
}
8788
DockerClient client = DockerClientFactory.lazyClient();
88-
String ryukImage = ImageNameSubstitutor.instance()
89-
.apply(DockerImageName.parse("testcontainers/ryuk:0.3.3"))
90-
.asCanonicalNameString();
91-
DockerClientFactory.instance().checkAndPullImage(client, ryukImage);
89+
RemoteDockerImage ryukImage = new RemoteDockerImage(DockerImageName.parse("testcontainers/ryuk:0.3.3"));
9290

9391
List<Bind> binds = new ArrayList<>();
9492
binds.add(new Bind(DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), new Volume("/var/run/docker.sock")));
9593

9694
ExposedPort ryukExposedPort = ExposedPort.tcp(8080);
97-
containerId = client.createContainerCmd(ryukImage)
95+
containerId = client.createContainerCmd(ryukImage.get())
9896
.withHostConfig(
9997
new HostConfig()
10098
.withAutoRemove(true)

core/src/test/java/org/testcontainers/DockerClientFactoryTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.assertj.core.api.Assertions.assertThatThrownBy;
5-
import static org.testcontainers.TestImages.TINY_IMAGE;
65

76
import com.github.dockerjava.api.exception.NotFoundException;
87
import org.junit.Rule;
98
import org.junit.Test;
109
import org.rnorth.visibleassertions.VisibleAssertions;
1110
import org.testcontainers.DockerClientFactory.DiskSpaceUsage;
1211
import org.testcontainers.dockerclient.LogToStringContainerCallback;
12+
import org.testcontainers.images.LocalImagesCacheAccessor;
13+
import org.testcontainers.utility.DockerImageName;
1314
import org.testcontainers.utility.MockTestcontainersConfigurationRule;
1415

1516
/**
@@ -24,16 +25,21 @@ public class DockerClientFactoryTest {
2425
public void runCommandInsideDockerShouldNotFailIfImageDoesNotExistsLocally() {
2526

2627
final DockerClientFactory dockFactory = DockerClientFactory.instance();
28+
29+
DockerImageName imageName = DockerImageName.parse("testcontainers/helloworld:1.1.0");
30+
2731
try {
2832
//remove tiny image, so it will be pulled during next command run
2933
dockFactory.client()
30-
.removeImageCmd(TINY_IMAGE.asCanonicalNameString())
34+
.removeImageCmd(imageName.asCanonicalNameString())
3135
.withForce(true).exec();
3236
} catch (NotFoundException ignored) {
3337
// Do not fail if it's not pulled yet
3438
}
39+
LocalImagesCacheAccessor.clearCache();
3540

3641
dockFactory.runInsideDocker(
42+
imageName,
3743
cmd -> cmd.withCmd("sh", "-c", "echo 'SUCCESS'"),
3844
(client, id) ->
3945
client.logContainerCmd(id)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.testcontainers.images;
2+
3+
public final class LocalImagesCacheAccessor {
4+
5+
public static synchronized void clearCache() {
6+
LocalImagesCache.INSTANCE.cache.clear();
7+
LocalImagesCache.INSTANCE.initialized.set(false);
8+
}
9+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.testcontainers.containers.ContainerState;
1818
import org.testcontainers.containers.DockerComposeContainer;
1919
import org.testcontainers.containers.GenericContainer;
20+
import org.testcontainers.images.LocalImagesCacheAccessor;
2021
import org.testcontainers.images.builder.ImageFromDockerfile;
2122

2223
import java.io.IOException;
@@ -93,6 +94,7 @@ public void removeImageFromLocalDocker() {
9394
} catch (NotFoundException ignored) {
9495

9596
}
97+
LocalImagesCacheAccessor.clearCache();
9698
}
9799

98100
@AfterClass

0 commit comments

Comments
 (0)