summaryrefslogtreecommitdiffstats
path: root/docker-api
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@verizonmedia.com>2019-06-12 10:58:31 +0200
committerHåkon Hallingstad <hakon@verizonmedia.com>2019-06-12 10:58:31 +0200
commitaab056aa72ef97c0a16661b994673bf4328e3b77 (patch)
treee1bda95267907dbaa57407e94e505896ae1a77bc /docker-api
parent4b044d83f36a296afec6778eff38f76395a36a5e (diff)
List containers on DockerOperations
Diffstat (limited to 'docker-api')
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerLite.java61
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java3
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollector.java6
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java11
-rw-r--r--docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollectionTest.java28
5 files changed, 80 insertions, 29 deletions
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerLite.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerLite.java
new file mode 100644
index 00000000000..51d815a412f
--- /dev/null
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/ContainerLite.java
@@ -0,0 +1,61 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.dockerapi;
+
+import java.util.Objects;
+
+/**
+ * Information about a container as a result of listing containers (aka "docker ps").
+ *
+ * @author hakonhall
+ */
+public class ContainerLite {
+ private final String id;
+ private final String imageId;
+ // state is one of: "running"
+ private final String state;
+
+ public ContainerLite(String id, String imageId, String state) {
+ this.id = id;
+ this.imageId = imageId;
+ this.state = state;
+ }
+
+ /** Of format: "94a66101b8dfbf485f4f77a448b079684ea704927aa39e31d824de708cfa3373" */
+ public String id() {
+ return id;
+ }
+
+ /** Of format: "sha256:7f3abbbbb17d135840a1f185ac291c87f7b90651e65b6021e820abaf397dd282" */
+ public String imageId() {
+ return imageId;
+ }
+
+ /** Whether the container is running. */
+ public boolean isRunning() {
+ return "running".equals(state);
+ }
+
+ @Override
+ public String toString() {
+ return "ContainerLite{" +
+ "id='" + id + '\'' +
+ ", imageId='" + imageId + '\'' +
+ ", state='" + state + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ContainerLite that = (ContainerLite) o;
+ return Objects.equals(id, that.id) &&
+ Objects.equals(imageId, that.imageId) &&
+ Objects.equals(state, that.state);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, imageId, state);
+ }
+}
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
index 8344830e229..1729c4843ef 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
@@ -81,6 +81,9 @@ public interface Docker {
*/
boolean pullImageAsyncIfNeeded(DockerImage image);
+ /** List all containers, including those not running. */
+ List<ContainerLite> listAllContainers();
+
/**
* Deletes the local images that are currently not in use by any container and not recently used.
*/
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollector.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollector.java
index 4eeb00c7685..242332ebd54 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollector.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollector.java
@@ -73,7 +73,7 @@ class DockerImageGarbageCollector {
*/
boolean deleteUnusedDockerImages(List<DockerImage> excludes, Duration minImageAgeToDelete) {
List<Image> images = docker.listAllImages();
- List<Container> containers = docker.listAllContainers();
+ List<ContainerLite> containers = docker.listAllContainers();
Map<String, Image> imageByImageId = images.stream().collect(Collectors.toMap(Image::getId, Function.identity()));
@@ -138,14 +138,14 @@ class DockerImageGarbageCollector {
.count() > 0;
}
- private Set<String> getRecentlyUsedImageIds(List<Image> images, List<Container> containers, Duration minImageAgeToDelete) {
+ private Set<String> getRecentlyUsedImageIds(List<Image> images, List<ContainerLite> containers, Duration minImageAgeToDelete) {
final Instant now = clock.instant();
// Add any already downloaded image to the list once
images.forEach(image -> lastTimeUsedByImageId.putIfAbsent(image.getId(), now));
// Update last used time for all current containers
- containers.forEach(container -> lastTimeUsedByImageId.put(container.getImageId(), now));
+ containers.forEach(container -> lastTimeUsedByImageId.put(container.imageId(), now));
// Return list of images that have been used within minImageAgeToDelete
return lastTimeUsedByImageId.entrySet().stream()
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
index 9299cedaf21..683c8a98788 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
@@ -42,6 +42,7 @@ import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DockerImpl implements Docker {
@@ -296,9 +297,15 @@ public class DockerImpl implements Docker {
return encodedContainerName.substring(FRAMEWORK_CONTAINER_PREFIX.length());
}
- List<com.github.dockerjava.api.model.Container> listAllContainers() {
+ @Override
+ public List<ContainerLite> listAllContainers() {
try {
- return dockerClient.listContainersCmd().withShowAll(true).exec();
+ return dockerClient.listContainersCmd().withShowAll(true).exec().stream()
+ .map(c -> new ContainerLite(
+ c.getId(), // Example: "94a66101b8dfbf485f4f77a448b079684ea704927aa39e31d824de708cfa3373"
+ c.getImageId(), // Example: "sha256:7f3abbbbb17d135840a1f185ac291c87f7b90651e65b6021e820abaf397dd282"
+ c.getState())) // Example: "running"
+ .collect(Collectors.toList());
} catch (RuntimeException e) {
numberOfDockerDaemonFails.add();
throw new DockerException("Failed to list all containers", e);
diff --git a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollectionTest.java b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollectionTest.java
index 412b8301e4c..520f8a74d58 100644
--- a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollectionTest.java
+++ b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/DockerImageGarbageCollectionTest.java
@@ -50,7 +50,7 @@ public class DockerImageGarbageCollectionTest {
@Test
public void singleImageWithContainerIsUsed() {
gcTester.withExistingImages(ImageBuilder.forId("image-1"))
- .andExistingContainers(ContainerBuilder.forId("container-1").withImageId("image-1"))
+ .andExistingContainers(new ContainerLite("container-1", "image-1", "running"))
.expectDeletedImages();
}
@@ -77,7 +77,7 @@ public class DockerImageGarbageCollectionTest {
ImageBuilder.forId("parent-image"),
ImageBuilder.forId("image-1").withParentId("parent-image").withTags("latest"),
ImageBuilder.forId("image-2").withParentId("parent-image").withTags("1.24"))
- .andExistingContainers(ContainerBuilder.forId("vespa-node-1").withImageId("image-1"))
+ .andExistingContainers(new ContainerLite("vespa-node-1", "image-1", "running"))
.expectDeletedImages("1.24"); // Deleting the only tag will delete the image
}
@@ -173,10 +173,8 @@ public class DockerImageGarbageCollectionTest {
return this;
}
- private ImageGcTester andExistingContainers(ContainerBuilder... containers) {
- when(docker.listAllContainers()).thenReturn(Arrays.stream(containers)
- .map(ContainerBuilder::toContainer)
- .collect(Collectors.toList()));
+ private ImageGcTester andExistingContainers(ContainerLite... containers) {
+ when(docker.listAllContainers()).thenReturn(List.of(containers));
return this;
}
@@ -257,22 +255,4 @@ public class DockerImageGarbageCollectionTest {
private ImageBuilder withTags(String... tags) { this.repoTags = tags; return this; }
private Image toImage() { return createFrom(Image.class, this); }
}
-
- // Workaround for Container class that can't be instantiated directly in Java (instantiate via Jackson instead).
- private static class ContainerBuilder {
- // Json property names must match exactly the property names in the Container class.
- @JsonProperty("Id")
- private final String id;
-
- @JsonProperty("ImageID")
- private String imageId;
-
- private ContainerBuilder(String id) { this.id = id; }
- private static ContainerBuilder forId(final String id) { return new ContainerBuilder(id); }
- private ContainerBuilder withImageId(String imageId) { this.imageId = imageId; return this; }
-
- private com.github.dockerjava.api.model.Container toContainer() {
- return createFrom(com.github.dockerjava.api.model.Container.class, this);
- }
- }
}