aboutsummaryrefslogtreecommitdiffstats
path: root/node-admin
diff options
context:
space:
mode:
authorvalerijf <valerijf@yahoo-inc.com>2016-08-04 09:08:47 +0200
committervalerijf <valerijf@yahoo-inc.com>2016-08-04 09:08:47 +0200
commit62078a8dfd919e46650c52b53b9c823f0341fdbe (patch)
tree89a668ef73b7260d82ace16429cd47602afd182f /node-admin
parente4de48dc7ba44c9066c56d7a0bbc6174f2ba4ca1 (diff)
Changed from spotify/docker to docker-java/docker-java
Diffstat (limited to 'node-admin')
-rw-r--r--node-admin/pom.xml48
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImpl.java252
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java83
3 files changed, 176 insertions, 207 deletions
diff --git a/node-admin/pom.xml b/node-admin/pom.xml
index 13031b2d429..66627c3390a 100644
--- a/node-admin/pom.xml
+++ b/node-admin/pom.xml
@@ -42,51 +42,9 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>com.spotify</groupId>
- <artifactId>docker-client</artifactId>
- <version>3.5.12</version>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.jaxrs</groupId>
- <artifactId>jackson-jaxrs-json-provider</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.glassfish.jersey.core</groupId>
- <artifactId>jersey-client</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.glassfish.jersey.core</groupId>
- <artifactId>jersey-common</artifactId>
- </exclusion>
- <exclusion>
- <groupId>javax.ws.rs</groupId>
- <artifactId>javax.ws.rs-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.glassfish.jersey.media</groupId>
- <artifactId>jersey-media-json-jackson</artifactId>
- </exclusion>
- <exclusion> <!-- Using network sockets instead of unix domain sockets -->
- <artifactId>jnr-unixsocket</artifactId>
- <groupId>com.github.jnr</groupId>
- </exclusion>
- </exclusions>
+ <groupId>com.github.docker-java</groupId>
+ <artifactId>docker-java</artifactId>
+ <version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImpl.java
index b013155563a..15fce17eaad 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImpl.java
@@ -1,24 +1,22 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.node.admin.docker;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerCmd;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.ExecCreateCmdResponse;
+import com.github.dockerjava.api.command.ExecStartCmd;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.command.InspectExecResponse;
+import com.github.dockerjava.api.exception.DockerException;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Image;
+import com.github.dockerjava.core.DefaultDockerClientConfig;
+import com.github.dockerjava.core.DockerClientImpl;
+import com.github.dockerjava.core.command.ExecStartResultCallback;
import com.google.common.base.Joiner;
import com.google.common.io.CharStreams;
import com.google.inject.Inject;
-import com.spotify.docker.client.ContainerNotFoundException;
-import com.spotify.docker.client.DefaultDockerClient;
-import com.spotify.docker.client.DockerCertificateException;
-import com.spotify.docker.client.DockerCertificates;
-import com.spotify.docker.client.DockerClient;
-import com.spotify.docker.client.DockerClient.ExecCreateParam;
-import com.spotify.docker.client.DockerException;
-import com.spotify.docker.client.LogStream;
-import com.spotify.docker.client.messages.ContainerConfig;
-import com.spotify.docker.client.messages.ContainerInfo;
-import com.spotify.docker.client.messages.ContainerState;
-import com.spotify.docker.client.messages.ExecState;
-import com.spotify.docker.client.messages.HostConfig;
-import com.spotify.docker.client.messages.Image;
-import com.spotify.docker.client.messages.RemovedImage;
import com.yahoo.nodeadmin.docker.DockerConfig;
import com.yahoo.vespa.applicationmodel.HostName;
import static com.yahoo.vespa.defaults.Defaults.getDefaults;
@@ -29,11 +27,12 @@ import com.yahoo.vespa.hosted.node.admin.util.PrefixLogger;
import com.yahoo.vespa.hosted.node.maintenance.Maintainer;
import javax.annotation.concurrent.GuardedBy;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
@@ -41,12 +40,11 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -105,36 +103,34 @@ public class DockerImpl implements Docker {
@Inject
public DockerImpl(final DockerConfig config) {
- this(DefaultDockerClient.builder().
- uri(config.uri()).
- dockerCertificates(certificates(config)).
- readTimeoutMillis(TimeUnit.MINUTES.toMillis(30)). // Some operations may take minutes.
- build());
+ this(DockerClientImpl.getInstance(new DefaultDockerClientConfig.Builder()
+ .withRegistryUrl(config.uri())
+ .withDockerCertPath(config.uri())
+ .withDockerTlsVerify(true)
+ .withProperties(certificates(config))
+ .build()));
}
-
- private static DockerCertificates certificates(DockerConfig config) {
- try {
- return DockerCertificates.builder()
- .caCertPath(Paths.get(config.caCertPath()))
- .clientCertPath(Paths.get(config.clientCertPath()))
- .clientKeyPath(Paths.get(config.clientKeyPath()))
- .build().get();
- } catch (DockerCertificateException e) {
- throw new RuntimeException("Failed configuring certificates for contacting docker daemon.", e);
- }
+ private static Properties certificates(DockerConfig config) {
+ NODE_ADMIN_LOGGER.info("tlscacert: " + config.caCertPath() + " | " +
+ "tlscert: " + config.clientCertPath() + " | " +
+ "tlskey: " + config.clientKeyPath());
+ Properties certificates = new Properties();
+ certificates.setProperty("tlscacert", config.caCertPath());
+ certificates.setProperty("tlscert", config.clientCertPath());
+ certificates.setProperty("tlskey", config.clientKeyPath());
+ return certificates;
}
+
@Override
public CompletableFuture<DockerImage> pullImageAsync(final DockerImage image) {
// We define the task before we create the CompletableFuture, to ensure that the local future variable cannot
// be accessed by the task, forcing it to always go through removeScheduledPoll() before completing the task.
final Runnable task = () -> {
try {
- docker.pull(image.asString());
+ docker.pullImageCmd(image.asString());
removeScheduledPoll(image).complete(image);
- } catch (InterruptedException e) {
- removeScheduledPoll(image).completeExceptionally(e);
} catch (DockerException e) {
if (imageIsDownloaded(image)) {
/* TODO: the docker client is not in sync with the server protocol causing it to throw
@@ -174,11 +170,11 @@ public class DockerImpl implements Docker {
@Override
public boolean imageIsDownloaded(final DockerImage dockerImage) {
try {
- List<Image> images = docker.listImages(DockerClient.ListImagesParam.allImages());
+ List<Image> images = docker.listImagesCmd().withShowAll(true).exec();
return images.stream().
- flatMap(image -> image.repoTags().stream()).
+ flatMap(image -> Arrays.stream(image.getRepoTags())).
anyMatch(tag -> tag.equals(dockerImage.asString()));
- } catch (DockerException|InterruptedException e) {
+ } catch (DockerException e) {
throw new RuntimeException("Failed to list image name: '" + dockerImage + "'", e);
}
}
@@ -193,38 +189,40 @@ public class DockerImpl implements Docker {
double minMainMemoryAvailableGb) {
try {
final double GIGA = Math.pow(2.0, 30.0);
+ InetAddress nodeInetAddress = Inet6Address.getByName(hostName.s());
+ String nodeIpAddress = nodeInetAddress.getHostAddress();
+ String hostIpAddress = Inet6Address.getLocalHost().getHostAddress();
+
+ CreateContainerCmd containerConfigBuilder = docker.createContainerCmd(dockerImage.asString())
+ .withImage(dockerImage.asString())
+ .withLabels(CONTAINER_LABELS)
+ .withEnv(new String[]{"CONFIG_SERVER_ADDRESS=" + Joiner.on(',').join(Environment.getConfigServerHosts())})
+ .withHostName(hostName.s())
+ .withNetworkMode("bridge")
+ .withBinds(applicationStorageToMount(containerName))
+ .withDns(hostIpAddress)
+ .withIpv6Address(nodeIpAddress);
+
+
// TODO: Enforce disk constraints
// TODO: Consider if CPU shares or quoata should be set. For now we are just assuming they are
// nicely controlled by docker.
- ContainerConfig.Builder containerConfigBuilder = ContainerConfig.builder().
- image(dockerImage.asString()).
- labels(CONTAINER_LABELS).
- hostConfig(
- HostConfig.builder()
- .networkMode("none")
- .binds(applicationStorageToMount(containerName))
- .build())
- .env("CONFIG_SERVER_ADDRESS=" + Joiner.on(',').join(Environment.getConfigServerHosts())).
- hostname(hostName.s());
- if (minMainMemoryAvailableGb > 0.00001) {
- containerConfigBuilder.memory((long) (GIGA * minMainMemoryAvailableGb));
- }
- docker.createContainer(containerConfigBuilder.build(), containerName.asString());
- //HostConfig hostConfig = HostConfig.builder().create();
- docker.startContainer(containerName.asString());
- ContainerInfo containerInfo = docker.inspectContainer(containerName.asString());
- ContainerState state = containerInfo.state();
-
- if (state.running()) {
- Integer pid = state.pid();
- if (pid == null) {
- throw new DockerException("PID of running container for host " + hostName + " is null");
- }
- setupContainerNetworking(containerName, hostName, pid);
+ if (minMainMemoryAvailableGb > 0.00001) {
+ containerConfigBuilder.withMemory((long) (GIGA * minMainMemoryAvailableGb));
}
- } catch (IOException | DockerException | InterruptedException e) {
+ CreateContainerResponse response = containerConfigBuilder.exec();
+ docker.startContainerCmd(response.getId()).exec();
+
+// if (state.running()) {
+// Integer pid = state.pid();
+// if (pid == null) {
+// throw new DockerException("PID of running container for host " + hostName + " is null");
+// }
+// setupContainerNetworking(containerName, hostName, pid);
+// }
+ } catch (IOException | DockerException e) {
throw new RuntimeException("Failed to start container " + containerName.asString(), e);
}
}
@@ -254,23 +252,21 @@ public class DockerImpl implements Docker {
public ProcessResult executeInContainer(ContainerName containerName, String... args) {
assert args.length >= 1;
try {
- final String execId = docker.execCreate(
- containerName.asString(),
- args,
- ExecCreateParam.attachStdout(),
- ExecCreateParam.attachStderr());
-
- try (final LogStream stream = docker.execStart(execId)) {
- // This will block until program exits
- final String output = stream.readFully();
-
- final ExecState state = docker.execInspect(execId);
- assert !state.running();
- Integer exitCode = state.exitCode();
- assert exitCode != null;
-
- return new ProcessResult(exitCode, output);
- }
+ final ExecCreateCmdResponse response = docker.execCreateCmd(containerName.asString())
+ .withCmd(args)
+ .withAttachStdout(true)
+ .exec();
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ExecStartCmd execStartCmd = docker.execStartCmd(response.getId());
+ execStartCmd.exec(new ExecStartResultCallback(output, output)).awaitCompletion();
+
+ final InspectExecResponse state = docker.inspectExecCmd(execStartCmd.getExecId()).exec();
+ assert !state.isRunning();
+ Integer exitCode = state.getExitCode();
+ assert exitCode != null;
+
+ return new ProcessResult(exitCode, new String(output.toByteArray()));
} catch (DockerException | InterruptedException e) {
throw new RuntimeException("Container " + containerName.asString()
+ " failed to execute " + Arrays.toString(args));
@@ -325,22 +321,23 @@ public class DockerImpl implements Docker {
}
}
- static List<String> applicationStorageToMount(ContainerName containerName) {
+ static List<Bind> applicationStorageToMount(ContainerName containerName) {
return Stream.concat(
Stream.of("/etc/hosts:/etc/hosts"),
DIRECTORIES_TO_MOUNT.stream().map(directory ->
Maintainer.pathInHostFromPathInNode(containerName, directory).toString() +
":" + directory))
+ .map(Bind::parse)
.collect(Collectors.toList());
}
@Override
public void stopContainer(final ContainerName containerName) {
- Optional<com.spotify.docker.client.messages.Container> dockerContainer = getContainerFromName(containerName, true);
+ Optional<com.github.dockerjava.api.model.Container> dockerContainer = getContainerFromName(containerName, true);
if (dockerContainer.isPresent()) {
try {
- docker.stopContainer(dockerContainer.get().id(), SECONDS_TO_WAIT_BEFORE_KILLING);
- } catch (DockerException|InterruptedException e) {
+ docker.stopContainerCmd(dockerContainer.get().getId()).withTimeout(SECONDS_TO_WAIT_BEFORE_KILLING).exec();
+ } catch (DockerException e) {
throw new RuntimeException("Failed to stop container", e);
}
}
@@ -348,11 +345,11 @@ public class DockerImpl implements Docker {
@Override
public void deleteContainer(ContainerName containerName) {
- Optional<com.spotify.docker.client.messages.Container> dockerContainer = getContainerFromName(containerName, true);
+ Optional<com.github.dockerjava.api.model.Container> dockerContainer = getContainerFromName(containerName, true);
if (dockerContainer.isPresent()) {
try {
- docker.removeContainer(dockerContainer.get().id());
- } catch (DockerException|InterruptedException e) {
+ docker.removeContainerCmd(dockerContainer.get().getId());
+ } catch (DockerException e) {
throw new RuntimeException("Failed to delete container", e);
}
}
@@ -362,11 +359,11 @@ public class DockerImpl implements Docker {
public List<Container> getAllManagedContainers() {
try {
- return docker.listContainers(DockerClient.ListContainersParam.allContainers(true)).stream().
- filter(this::isManaged).
- flatMap(this::asContainer).
- collect(Collectors.toList());
- } catch (DockerException|InterruptedException e) {
+ return docker.listContainersCmd().withShowAll(true).exec().stream()
+ .filter(this::isManaged)
+ .flatMap(this::asContainer)
+ .collect(Collectors.toList());
+ } catch (DockerException e) {
throw new RuntimeException("Failed to delete container", e);
}
}
@@ -379,45 +376,45 @@ public class DockerImpl implements Docker {
.findFirst();
}
- private Stream<Container> asContainer(com.spotify.docker.client.messages.Container dockerClientContainer) {
+ private Stream<Container> asContainer(com.github.dockerjava.api.model.Container dockerClientContainer) {
try {
- final ContainerInfo containerInfo = docker.inspectContainer(dockerClientContainer.id());
+ final InspectContainerResponse response = docker.inspectContainerCmd(dockerClientContainer.getId()).exec();
return Stream.of(new Container(
- new HostName(containerInfo.config().hostname()),
- new DockerImage(dockerClientContainer.image()),
- new ContainerName(decode(containerInfo.name())),
- containerInfo.state().running()));
- } catch(ContainerNotFoundException e) {
- return Stream.empty();
- } catch (InterruptedException|DockerException e) {
+ new HostName(response.getConfig().getHostName()),
+ new DockerImage(dockerClientContainer.getImage()),
+ new ContainerName(decode(response.getName())),
+ response.getState().getRunning()));
+ } catch (DockerException e) {
//TODO: do proper exception handling
throw new RuntimeException("Failed talking to docker daemon", e);
}
}
- private Optional<com.spotify.docker.client.messages.Container> getContainerFromName(
+ private Optional<com.github.dockerjava.api.model.Container> getContainerFromName(
final ContainerName containerName, final boolean alsoGetStoppedContainers) {
try {
- return docker.listContainers(DockerClient.ListContainersParam.allContainers(alsoGetStoppedContainers)).stream().
- filter(this::isManaged).
- filter(container -> matchName(container, containerName.asString())).
+ return docker.listContainersCmd().withShowAll(alsoGetStoppedContainers).exec().stream()
+ .filter(this::isManaged)
+ .filter(container -> matchName(container, containerName.asString())).
findFirst();
- } catch (DockerException|InterruptedException e) {
+ } catch (DockerException e) {
throw new RuntimeException("Failed to get container from name", e);
}
}
- private boolean isManaged(final com.spotify.docker.client.messages.Container container) {
- final Map<String, String> labels = container.labels();
+
+
+ private boolean isManaged(final com.github.dockerjava.api.model.Container container) {
+ final Map<String, String> labels = container.getLabels();
if (labels == null) {
return false;
}
return LABEL_VALUE_MANAGEDBY.equals(labels.get(LABEL_NAME_MANAGEDBY));
}
- private boolean matchName(com.spotify.docker.client.messages.Container container, String targetName) {
- return container.names().stream().anyMatch(encodedName -> decode(encodedName).equals(targetName));
+ private boolean matchName(com.github.dockerjava.api.model.Container container, String targetName) {
+ return Arrays.stream(container.getNames()).anyMatch(encodedName -> decode(encodedName).equals(targetName));
}
private String decode(String encodedContainerName) {
@@ -428,14 +425,7 @@ public class DockerImpl implements Docker {
public void deleteImage(final DockerImage dockerImage) {
try {
NODE_ADMIN_LOGGER.info("Deleting docker image " + dockerImage);
- final List<RemovedImage> removedImages = docker.removeImage(dockerImage.asString());
- for (RemovedImage removedImage : removedImages) {
- if (removedImage.type() != RemovedImage.Type.DELETED) {
- NODE_ADMIN_LOGGER.info("Result of deleting docker image " + dockerImage + ": " + removedImage);
- }
- }
- } catch (InterruptedException e) {
- throw new RuntimeException("Unexpected interrupt", e);
+ docker.removeImageCmd(dockerImage.asString()).exec();
} catch (DockerException e) {
NODE_ADMIN_LOGGER.warning("Could not delete docker image " + dockerImage, e);
}
@@ -458,21 +448,21 @@ public class DockerImpl implements Docker {
final Map<String, String> dependencies = new HashMap<>();
// Populate maps with images (including tags) and their dependencies (parents).
- for (Image image : docker.listImages(DockerClient.ListImagesParam.allImages())) {
- objects.put(image.id(), new DockerObject(image.id(), DockerObjectType.IMAGE));
- if (image.parentId() != null && !image.parentId().isEmpty()) {
- dependencies.put(image.id(), image.parentId());
+ for (Image image : docker.listImagesCmd().withShowAll(true).exec()) {
+ objects.put(image.getId(), new DockerObject(image.getId(), DockerObjectType.IMAGE));
+ if (image.getParentId() != null && !image.getParentId().isEmpty()) {
+ dependencies.put(image.getId(), image.getParentId());
}
- for (String tag : image.repoTags()) {
+ for (String tag : image.getRepoTags()) {
objects.put(tag, new DockerObject(tag, DockerObjectType.IMAGE_TAG));
- dependencies.put(tag, image.id());
+ dependencies.put(tag, image.getId());
}
}
// Populate maps with containers and their dependency to the image they run on.
- for (com.spotify.docker.client.messages.Container container : docker.listContainers(DockerClient.ListContainersParam.allContainers(true))) {
- objects.put(container.id(), new DockerObject(container.id(), DockerObjectType.CONTAINER));
- dependencies.put(container.id(), container.image());
+ for (com.github.dockerjava.api.model.Container container : docker.listContainersCmd().withShowAll(true).exec()) {
+ objects.put(container.getId(), new DockerObject(container.getId(), DockerObjectType.CONTAINER));
+ dependencies.put(container.getId(), container.getImage());
}
// Now update every object with its dependencies.
@@ -488,7 +478,7 @@ public class DockerImpl implements Docker {
.map(obj -> obj.id)
.map(DockerImage::new)
.collect(Collectors.toSet());
- } catch (InterruptedException|DockerException e) {
+ } catch (DockerException e) {
throw new RuntimeException("Unexpected exception", e);
}
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java
index 5656627bbba..3a02c56b300 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java
@@ -4,13 +4,13 @@ package com.yahoo.vespa.hosted.node.admin.docker;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.spotify.docker.client.DockerClient;
-import com.spotify.docker.client.LogStream;
-import com.spotify.docker.client.ObjectMapperProvider;
-import com.spotify.docker.client.messages.ExecState;
-import com.spotify.docker.client.messages.Image;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.ExecCreateCmdResponse;
+import com.github.dockerjava.api.command.ListContainersCmd;
+import com.github.dockerjava.api.command.ListImagesCmd;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Image;
import com.yahoo.vespa.defaults.Defaults;
-import com.yahoo.vespa.hosted.node.maintenance.Maintainer;
import org.junit.Test;
import java.io.IOException;
@@ -44,11 +44,11 @@ import static org.mockito.Mockito.when;
public class DockerImplTest {
@Test
public void data_directories_are_mounted_in_from_the_host() {
- List<String> binds = DockerImpl.applicationStorageToMount(new ContainerName("my-container"));
+ List<Bind> binds = DockerImpl.applicationStorageToMount(new ContainerName("my-container"));
String dataDirectory = Defaults.getDefaults().vespaHome() + "logs";
String directoryOnHost = "/home/docker/container-storage/my-container" + dataDirectory;
- assertThat(binds, hasItem(directoryOnHost + ":" + dataDirectory));
+ assertThat(binds, hasItem(Bind.parse(directoryOnHost + ":" + dataDirectory)));
}
@Test
@@ -58,7 +58,7 @@ public class DockerImplTest {
doAnswer(invocationOnMock -> {
latch.await();
return null;
- }).when(dockerClient).pull(any(String.class));
+ }).when(dockerClient).pullImageCmd(any(String.class)).exec(any());
final Docker docker = new DockerImpl(dockerClient);
final DockerImage dockerImage = new DockerImage("test-image");
@@ -116,28 +116,43 @@ public class DockerImplTest {
@Test
public void testExecuteCompletes() throws Exception {
+
+// ByteArrayOutputStream output = new ByteArrayOutputStream();
+// ExecStartCmd execStartCmd = docker.execStartCmd(response.getId());
+// execStartCmd.exec(new ExecStartResultCallback(output, output)).awaitCompletion();
+//
+// final InspectExecResponse state = docker.inspectExecCmd(execStartCmd.getExecId()).exec();
+// assert !state.isRunning();
+// Integer exitCode = state.getExitCode();
+// assert exitCode != null;
+
+
+ final ExecCreateCmdResponse response = mock(ExecCreateCmdResponse.class);
final DockerClient dockerClient = mock(DockerClient.class);
final String containerId = "container-id";
final String[] command = new String[] {"/bin/ls", "-l"};
final String execId = "exec-id";
- when(dockerClient.execCreate(
- eq(containerId),
- eq(command),
- anyVararg(),
- anyVararg())).thenReturn(execId);
-
- final LogStream logStream = mock(LogStream.class);
- when(dockerClient.execStart(execId)).thenReturn(logStream);
-
- final ExecState execState = mock(ExecState.class);
- when(dockerClient.execInspect(execId)).thenReturn(execState);
+ final String commandOutput = "command output";
- when(execState.running()).thenReturn(false);
+ when(response.getId()).thenReturn(execId);
+
+ when(dockerClient.execCreateCmd(eq(containerId))
+ .withCmd(eq(command))
+ .withAttachStdout(true)
+ .exec())
+ .thenReturn(response);
+
+// final LogStream logStream = mock(LogStream.class);
+// when(dockerClient.execStart(execId)).thenReturn(logStream);
+//
+// final ExecState execState = mock(ExecState.class);
+// when(dockerClient.execInspect(execId)).thenReturn(execState);
+//
+// when(execState.running()).thenReturn(false);
final int exitCode = 3;
- when(execState.exitCode()).thenReturn(exitCode);
-
- final String commandOutput = "command output";
- when(logStream.readFully()).thenReturn(commandOutput);
+// when(execState.exitCode()).thenReturn(exitCode);
+//
+// when(logStream.readFully()).thenReturn(commandOutput);
final Docker docker = new DockerImpl(dockerClient);
final ProcessResult result = docker.executeInContainer(new ContainerName(containerId), command);
@@ -223,7 +238,7 @@ public class DockerImplTest {
private static class ImageGcTester {
private final List<Image> existingImages;
- private List<com.spotify.docker.client.messages.Container> existingContainers = Collections.emptyList();
+ private List<com.github.dockerjava.api.model.Container> existingContainers = Collections.emptyList();
private ImageGcTester(final List<Image> images) {
this.existingImages = images;
@@ -246,8 +261,14 @@ public class DockerImplTest {
public void expectUnusedImages(final String... imageIds) throws Exception {
final DockerClient dockerClient = mock(DockerClient.class);
final Docker docker = new DockerImpl(dockerClient);
- when(dockerClient.listImages(anyVararg())).thenReturn(existingImages);
- when(dockerClient.listContainers(anyVararg())).thenReturn(existingContainers);
+ final ListImagesCmd listImagesCmd = mock(ListImagesCmd.class);
+ final ListContainersCmd listContainersCmd = mock(ListContainersCmd.class);
+
+ when(dockerClient.listImagesCmd()).thenReturn(listImagesCmd);
+ when(listImagesCmd.exec()).thenReturn(existingImages);
+
+ when(dockerClient.listContainersCmd()).thenReturn(listContainersCmd);
+ when(listContainersCmd.exec()).thenReturn(existingContainers);
final Set<DockerImage> expectedUnusedImages = Arrays.stream(imageIds)
.map(DockerImage::new)
.collect(Collectors.toSet());
@@ -272,7 +293,7 @@ public class DockerImplTest {
+ toClass + " with Jackson: " + e, e);
}
try {
- return new ObjectMapperProvider().getContext(null).readValue(serialized, toClass);
+ return new ObjectMapper().readValue(serialized, toClass);
} catch (IOException e) {
throw new IllegalArgumentException("Failed to convert " + serialized + " to "
+ toClass + " with Jackson: " + e, e);
@@ -313,8 +334,8 @@ public class DockerImplTest {
private static ContainerBuilder forId(final String id) { return new ContainerBuilder(id); }
public ContainerBuilder withImage(String image) { this.image = image; return this; }
- public com.spotify.docker.client.messages.Container toContainer() {
- return createFrom(com.spotify.docker.client.messages.Container.class, this);
+ public com.github.dockerjava.api.model.Container toContainer() {
+ return createFrom(com.github.dockerjava.api.model.Container.class, this);
}
}
}