summaryrefslogtreecommitdiffstats
path: root/node-admin/src/test/java
diff options
context:
space:
mode:
Diffstat (limited to 'node-admin/src/test/java')
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ContainerNameTest.java40
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java301
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerTest.java175
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ProcessResultTest.java25
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ComponentsProviderWithMocks.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerFailTest.java16
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java79
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MaintenanceSchedulerMock.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MultiDockerTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeRepoMock.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeStateTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ResumeTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminImplTest.java8
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminStateUpdaterTest.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/DockerOperationsTest.java50
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java213
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java4
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/maintenance/MaintainerTest.java2
18 files changed, 207 insertions, 728 deletions
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ContainerNameTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ContainerNameTest.java
deleted file mode 100644
index bf157779c43..00000000000
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ContainerNameTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.yahoo.vespa.hosted.node.admin.docker;
-
-import org.junit.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-/**
- * @author valerijf
- */
-public class ContainerNameTest {
- @Test
- public void testAlphanumericalContainerName() {
- String name = "container123";
- ContainerName containerName = new ContainerName(name);
- assertThat(containerName.asString(), is(name));
- }
-
- @Test
- public void testAlphanumericalWithDashContainerName() {
- String name = "container-123";
- ContainerName containerName = new ContainerName(name);
- assertThat(containerName.asString(), is(name));
- }
-
- @Test(expected=IllegalArgumentException.class)
- public void testAlphanumericalWithSlashContainerName() {
- new ContainerName("container/123");
- }
-
- @Test(expected=IllegalArgumentException.class)
- public void testEmptyContainerName() {
- new ContainerName("");
- }
-
- @Test(expected=NullPointerException.class)
- public void testNullContainerName() {
- new ContainerName(null);
- }
-}
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
deleted file mode 100644
index fcae057d42d..00000000000
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerImplTest.java
+++ /dev/null
@@ -1,301 +0,0 @@
-// 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.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.command.ExecCreateCmd;
-import com.github.dockerjava.api.command.ExecCreateCmdResponse;
-import com.github.dockerjava.api.command.ExecStartCmd;
-import com.github.dockerjava.api.command.InspectExecCmd;
-import com.github.dockerjava.api.command.InspectExecResponse;
-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.github.dockerjava.core.command.ExecStartResultCallback;
-import com.yahoo.vespa.defaults.Defaults;
-import org.junit.Test;
-import org.mockito.Matchers;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.hamcrest.CoreMatchers.hasItem;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-/**
- * @author tonytv
- */
-public class DockerImplTest {
- @Test
- public void data_directories_are_mounted_in_from_the_host() {
- 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(Bind.parse(directoryOnHost + ":" + dataDirectory)));
- }
-
- @Test
- public void vespaVersionIsParsed() {
- assertThat(DockerImpl.parseVespaVersion("5.119.53"), is(Optional.of("5.119.53")));
- }
-
- @Test
- public void vespaVersionIsParsedWithSpacesAndNewlines() {
- assertThat(DockerImpl.parseVespaVersion("5.119.53\n"), is(Optional.of("5.119.53")));
- assertThat(DockerImpl.parseVespaVersion(" 5.119.53 \n"), is(Optional.of("5.119.53")));
- assertThat(DockerImpl.parseVespaVersion("\n 5.119.53 \n"), is(Optional.of("5.119.53")));
- }
-
- @Test
- public void vespaVersionIsParsedWithIrregularVersionScheme() {
- assertThat(DockerImpl.parseVespaVersion("7.2"), is(Optional.of("7.2")));
- assertThat(DockerImpl.parseVespaVersion("8.0-beta"), is(Optional.of("8.0-beta")));
- assertThat(DockerImpl.parseVespaVersion("foo"), is(Optional.of("foo")));
- assertThat(DockerImpl.parseVespaVersion("119"), is(Optional.of("119")));
- }
-
- @Test
- public void vespaVersionIsNotParsedFromNull() {
- assertThat(DockerImpl.parseVespaVersion(null), is(Optional.empty()));
- }
-
- @Test
- public void vespaVersionIsNotParsedFromEmptyString() {
- assertThat(DockerImpl.parseVespaVersion(""), is(Optional.empty()));
- }
-
- @Test
- public void vespaVersionIsNotParsedFromUnexpectedContent() {
- assertThat(DockerImpl.parseVespaVersion("No such command 'vespanodectl'"), is(Optional.empty()));
- }
-
- @Test
- public void testExecuteCompletes() throws Exception {
- final String containerId = "container-id";
- final String[] command = new String[] {"/bin/ls", "-l"};
- final String execId = "exec-id";
- final int exitCode = 3;
-
- final DockerClient dockerClient = mock(DockerClient.class);
-
- final ExecCreateCmdResponse response = mock(ExecCreateCmdResponse.class);
- when(response.getId()).thenReturn(execId);
-
- final ExecCreateCmd execCreateCmd = mock(ExecCreateCmd.class);
- when(dockerClient.execCreateCmd(any(String.class))).thenReturn(execCreateCmd);
- when(execCreateCmd.withCmd(Matchers.<String>anyVararg())).thenReturn(execCreateCmd);
- when(execCreateCmd.withAttachStdout(any(Boolean.class))).thenReturn(execCreateCmd);
- when(execCreateCmd.withAttachStderr(any(Boolean.class))).thenReturn(execCreateCmd);
- when(execCreateCmd.exec()).thenReturn(response);
-
- final ExecStartCmd execStartCmd = mock(ExecStartCmd.class);
- when(dockerClient.execStartCmd(any(String.class))).thenReturn(execStartCmd);
- when(execStartCmd.exec(any(ExecStartResultCallback.class))).thenReturn(mock(ExecStartResultCallback.class));
-
- final InspectExecCmd inspectExecCmd = mock(InspectExecCmd.class);
- final InspectExecResponse state = mock(InspectExecResponse.class);
- when(dockerClient.inspectExecCmd(any(String.class))).thenReturn(inspectExecCmd);
- when(inspectExecCmd.exec()).thenReturn(state);
- when(state.isRunning()).thenReturn(false);
- when(state.getExitCode()).thenReturn(exitCode);
-
- final Docker docker = new DockerImpl(dockerClient);
- final ProcessResult result = docker.executeInContainer(new ContainerName(containerId), command);
- assertThat(result.getExitStatus(), is(exitCode));
- }
-
- @Test
- public void noImagesMeansNoUnusedImages() throws Exception {
- ImageGcTester
- .withExistingImages()
- .expectUnusedImages();
- }
-
- @Test
- public void singleImageWithoutContainersIsUnused() throws Exception {
- ImageGcTester
- .withExistingImages(new ImageBuilder("image-1"))
- .expectUnusedImages("image-1");
- }
-
- @Test
- public void singleImageWithContainerIsUsed() throws Exception {
- ImageGcTester
- .withExistingImages(ImageBuilder.forId("image-1"))
- .andExistingContainers(ContainerBuilder.forId("container-1").withImage("image-1"))
- .expectUnusedImages();
- }
-
- @Test
- public void onlyLeafImageIsUnused() throws Exception {
- ImageGcTester
- .withExistingImages(
- ImageBuilder.forId("parent-image"),
- ImageBuilder.forId("leaf-image").withParentId("parent-image"))
- .expectUnusedImages("leaf-image");
- }
-
- @Test
- public void multipleUnusedImagesAreIdentified() throws Exception {
- ImageGcTester
- .withExistingImages(
- ImageBuilder.forId("image-1"),
- ImageBuilder.forId("image-2"))
- .expectUnusedImages("image-1", "image-2");
- }
-
- @Test
- public void multipleUnusedLeavesAreIdentified() throws Exception {
- ImageGcTester
- .withExistingImages(
- ImageBuilder.forId("parent-image"),
- ImageBuilder.forId("image-1").withParentId("parent-image"),
- ImageBuilder.forId("image-2").withParentId("parent-image"))
- .expectUnusedImages("image-1", "image-2");
- }
-
- @Test
- public void unusedLeafWithUsedSiblingIsIdentified() throws Exception {
- ImageGcTester
- .withExistingImages(
- ImageBuilder.forId("parent-image"),
- ImageBuilder.forId("image-1").withParentId("parent-image"),
- ImageBuilder.forId("image-2").withParentId("parent-image"))
- .andExistingContainers(ContainerBuilder.forId("vespa-node-1").withImage("image-1"))
- .expectUnusedImages("image-2");
- }
-
- @Test
- public void containerCanReferToImageByTag() throws Exception {
- ImageGcTester
- .withExistingImages(ImageBuilder.forId("image-1").withTag("vespa-6"))
- .andExistingContainers(ContainerBuilder.forId("vespa-node-1").withImage("vespa-6"))
- .expectUnusedImages();
- }
-
- @Test
- public void taggedImageWithNoContainersIsUnused() throws Exception {
- ImageGcTester
- .withExistingImages(ImageBuilder.forId("image-1").withTag("vespa-6"))
- .expectUnusedImages("image-1");
- }
-
- private static class ImageGcTester {
- private final List<Image> existingImages;
- private List<com.github.dockerjava.api.model.Container> existingContainers = Collections.emptyList();
-
- private ImageGcTester(final List<Image> images) {
- this.existingImages = images;
- }
-
- public static ImageGcTester withExistingImages(final ImageBuilder... images) {
- final List<Image> existingImages = Arrays.stream(images)
- .map(ImageBuilder::toImage)
- .collect(Collectors.toList());
- return new ImageGcTester(existingImages);
- }
-
- public ImageGcTester andExistingContainers(final ContainerBuilder... containers) {
- this.existingContainers = Arrays.stream(containers)
- .map(ContainerBuilder::toContainer)
- .collect(Collectors.toList());
- return this;
- }
-
- public void expectUnusedImages(final String... imageIds) throws Exception {
- final DockerClient dockerClient = mock(DockerClient.class);
- final Docker docker = new DockerImpl(dockerClient);
- final ListImagesCmd listImagesCmd = mock(ListImagesCmd.class);
- final ListContainersCmd listContainersCmd = mock(ListContainersCmd.class);
-
- when(dockerClient.listImagesCmd()).thenReturn(listImagesCmd);
- when(listImagesCmd.withShowAll(true)).thenReturn(listImagesCmd);
- when(listImagesCmd.exec()).thenReturn(existingImages);
-
- when(dockerClient.listContainersCmd()).thenReturn(listContainersCmd);
- when(listContainersCmd.withShowAll(true)).thenReturn(listContainersCmd);
- when(listContainersCmd.exec()).thenReturn(existingContainers);
-
- final Set<DockerImage> expectedUnusedImages = Arrays.stream(imageIds)
- .map(DockerImage::new)
- .collect(Collectors.toSet());
- assertThat(
- docker.getUnusedDockerImages(),
- is(expectedUnusedImages));
-
- }
- }
-
- /**
- * Serializes object to a JSON string using Jackson, then deserializes it to an instance of toClass
- * (again using Jackson). This can be used to create Jackson classes with no public constructors.
- * @throws IllegalArgumentException if Jackson fails to serialize or deserialize.
- */
- private static <T> T createFrom(Class<T> toClass, Object object) throws IllegalArgumentException {
- final String serialized;
- try {
- serialized = new ObjectMapper().writeValueAsString(object);
- } catch (JsonProcessingException e) {
- throw new IllegalArgumentException("Failed to serialize object " + object + " to "
- + toClass + " with Jackson: " + e, e);
- }
- try {
- return new ObjectMapper().readValue(serialized, toClass);
- } catch (IOException e) {
- throw new IllegalArgumentException("Failed to convert " + serialized + " to "
- + toClass + " with Jackson: " + e, e);
- }
- }
-
- // Workaround for Image class that can't be instantiated directly in Java (instantiate via Jackson instead).
- private static class ImageBuilder {
- // Json property names must match exactly the property names in the Image class.
- @JsonProperty("Id")
- private final String id;
-
- @JsonProperty("ParentId")
- private String parentId;
-
- @JsonProperty("RepoTags")
- private final List<String> repoTags = new LinkedList<>();
-
- private ImageBuilder(String id) { this.id = id; }
-
- public static ImageBuilder forId(String id) { return new ImageBuilder(id); }
- public ImageBuilder withParentId(String parentId) { this.parentId = parentId; return this; }
- public ImageBuilder withTag(String tag) { this.repoTags.add(tag); return this; }
-
- public 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("Image")
- private String image;
-
- private ContainerBuilder(String id) { this.id = id; }
- private static ContainerBuilder forId(final String id) { return new ContainerBuilder(id); }
- public ContainerBuilder withImage(String image) { this.image = image; return this; }
-
- public com.github.dockerjava.api.model.Container toContainer() {
- return createFrom(com.github.dockerjava.api.model.Container.class, this);
- }
- }
-}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerTest.java
deleted file mode 100644
index bccd9b79070..00000000000
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.yahoo.vespa.hosted.node.admin.docker;
-
-import com.github.dockerjava.api.model.Network;
-import com.github.dockerjava.core.command.BuildImageResultCallback;
-import com.yahoo.nodeadmin.docker.DockerConfig;
-import com.yahoo.vespa.applicationmodel.HostName;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Collections;
-import java.util.concurrent.ExecutionException;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author valerijf
- */
-public class DockerTest {
- /**
- * To run these tests:
- * 1. Remove Ignore annotations
- * 2. Change ownership of docker.sock
- * $ sudo chown <your username> /var/run/docker.sock
- * 3. (Temporary) Manually create the docker network used by DockerImpl by running:
- * $ sudo docker network create --ipv6 --gateway=<your local IPv6 address> --subnet=fe80::1/16 habla
- * 4. (Temporary) Manually build docker test image. Inside src/test/resources/simple-ipv6-server run:
- * $ sudo docker build -t "simple-ipv6-server:Dockerfile" .
- * 5. (Temporary) Comment out setup() and shutdown()
- */
- private static final DockerConfig dockerConfig = new DockerConfig(new DockerConfig.Builder()
- .caCertPath("") // Temporary setting it to empty as this field is required, in the future
- .clientCertPath("") // DockerConfig should be rewritten and probably moved to docker-api module
- .clientKeyPath("")
- .uri("unix:///var/run/docker.sock"));
-
- private static final DockerImpl docker = new DockerImpl(dockerConfig);
- private static final DockerImage dockerImage = new DockerImage("simple-ipv6-server:Dockerfile");
-
-
- @Ignore
- @Test
- public void testDockerImagePull() throws ExecutionException, InterruptedException {
- DockerImage dockerImage = new DockerImage("busybox:1.24.0");
-
- // Pull the image and wait for the pull to complete
- docker.pullImageAsync(dockerImage).get();
-
- // Translate the human readable ID to sha256-hash ID that is returned by getUnusedDockerImages()
- DockerImage targetImage = new DockerImage(docker.docker.inspectImageCmd(dockerImage.asString()).exec().getId());
- assertTrue("Image: " + dockerImage + " should be unused", docker.getUnusedDockerImages().contains(targetImage));
-
- // Remove the image
- docker.deleteImage(dockerImage);
- assertFalse("Failed to delete " + dockerImage.asString() + " image", docker.imageIsDownloaded(dockerImage));
- }
-
- @Ignore
- @Test
- public void testDockerNetworking() throws InterruptedException, ExecutionException, IOException {
- HostName hostName1 = new HostName("docker10.test.yahoo.com");
- HostName hostName2 = new HostName("docker11.test.yahoo.com");
- ContainerName containerName1 = new ContainerName("test-container-1");
- ContainerName containerName2 = new ContainerName("test-container-2");
- InetAddress inetAddress1 = Inet6Address.getByName("fe80::10");
- InetAddress inetAddress2 = Inet6Address.getByName("fe80::11");
-
- docker.startContainer(dockerImage, hostName1, containerName1, inetAddress1, 0, 0, 0);
- docker.startContainer(dockerImage, hostName2, containerName2, inetAddress2, 0, 0, 0);
-
- try {
- testReachabilityFromHost(containerName1, inetAddress1);
- testReachabilityFromHost(containerName2, inetAddress2);
-
- String[] curlFromNodeToNode = new String[]{"curl", "-g", "http://[" + inetAddress2.getHostAddress() + "%eth0]/ping"};
- while (! docker.executeInContainer(containerName1, curlFromNodeToNode).isSuccess()) {
- Thread.sleep(20);
- }
- ProcessResult result = docker.executeInContainer(containerName1, curlFromNodeToNode);
- assertTrue("Could not reach " + containerName2.asString() + " from " + containerName1.asString(),
- result.getOutput().equals("pong\n"));
- } finally {
- docker.stopContainer(containerName1);
- docker.deleteContainer(containerName1);
-
- docker.stopContainer(containerName2);
- docker.deleteContainer(containerName2);
- }
- }
-
- private void testReachabilityFromHost(ContainerName containerName, InetAddress target) throws IOException, InterruptedException {
- String[] curlNodeFromHost = {"curl", "-g", "http://[" + target.getHostAddress() + "%" + getInterfaceName() + "]/ping"};
- while (!exec(curlNodeFromHost).equals("pong\n")) {
- Thread.sleep(20);
- }
- assertTrue("Could not reach " + containerName.asString() + " from host", exec(curlNodeFromHost).equals("pong\n"));
- }
-
-
- /**
- * Returns IPv6 address of on the "docker0" interface that can be reached by the containers
- */
- private static String getLocalIPv6Address() throws SocketException {
- return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
- .filter(networkInterface -> networkInterface.getDisplayName().equals("docker0"))
- .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
- .filter(ip -> ip instanceof Inet6Address && ip.isLinkLocalAddress())
- .findFirst().orElseThrow(RuntimeException::new)
- .getHostAddress().split("%")[0];
- }
-
- /**
- * Returns the display name of the bridge used by our custom docker network. This is used for routing in the
- * network tests. The bridge is assumed to be the only IPv6 interface starting with "br-"
- */
- private static String getInterfaceName() throws SocketException {
- return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
- .filter(networkInterface -> networkInterface.getDisplayName().startsWith("br-") &&
- networkInterface.getInterfaceAddresses().stream()
- .anyMatch(ip -> ip.getAddress() instanceof Inet6Address))
- .findFirst().orElseThrow(RuntimeException::new).getDisplayName();
- }
-
- /**
- * Synchronously executes a system process and returns its stdout. Based of {@link com.yahoo.system.ProcessExecuter}
- * but could not be reused because of import errors.
- */
- private static String exec(String[] command) throws IOException, InterruptedException {
- ProcessBuilder pb = new ProcessBuilder(command);
- StringBuilder ret = new StringBuilder();
-
- Process p = pb.start();
- InputStream is = p.getInputStream();
- while (true) {
- int b = is.read();
- if (b==-1) break;
- ret.append((char) b);
- }
-
- p.waitFor();
- p.destroy();
-
- return ret.toString();
- }
-
- @Before
- public void setup() throws IOException, ExecutionException, InterruptedException {
- // Build the image locally
- File dockerFilePath = new File("src/test/resources/simple-ipv6-server");
- docker.docker
- .buildImageCmd(dockerFilePath)
- .withTag(dockerImage.asString()).exec(new BuildImageResultCallback()).awaitCompletion();
-
- // Create a temporary network
- Network.Ipam ipam = new Network.Ipam().withConfig(new Network.Ipam.Config()
- .withSubnet("fe80::1/16").withGateway(getLocalIPv6Address()));
- docker.docker.createNetworkCmd().withDriver("bridge").withName(DockerImpl.DOCKER_CUSTOM_IP6_NETWORK_NAME)
- .withIpam(ipam).exec();
- }
-
- @After
- public void shutdown() {
- // Remove the network we created earlier
- docker.docker.removeNetworkCmd(DockerImpl.DOCKER_CUSTOM_IP6_NETWORK_NAME).exec();
- }
-}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ProcessResultTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ProcessResultTest.java
deleted file mode 100644
index 60ac91025ee..00000000000
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/ProcessResultTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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 org.junit.Test;
-
-import java.io.IOException;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-public class ProcessResultTest {
- @Test
- public void testBasicProperties() throws Exception {
- ProcessResult processResult = new ProcessResult(0, "foo", "bar");
- assertThat(processResult.getExitStatus(), is(0));
- assertThat(processResult.getOutput(), is("foo"));
- assertThat(processResult.isSuccess(), is(true));
- }
-
- @Test
- public void testSuccessFails() throws Exception {
- ProcessResult processResult = new ProcessResult(1, "foo", "bar");
- assertThat(processResult.isSuccess(), is(false));
- }
-}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ComponentsProviderWithMocks.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ComponentsProviderWithMocks.java
index 37018ff0a0d..004265f3346 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ComponentsProviderWithMocks.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ComponentsProviderWithMocks.java
@@ -7,7 +7,7 @@ import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminImpl;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdater;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgent;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentImpl;
-import com.yahoo.vespa.hosted.node.admin.docker.Docker;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
import com.yahoo.vespa.hosted.node.admin.nodeagent.DockerOperations;
import com.yahoo.vespa.hosted.node.admin.provider.ComponentsProvider;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerFailTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerFailTest.java
index e97f4acda87..3583054bec7 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerFailTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerFailTest.java
@@ -3,8 +3,8 @@ package com.yahoo.vespa.hosted.node.admin.integrationTests;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdmin;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminImpl;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdater;
@@ -73,11 +73,10 @@ public class DockerFailTest {
Thread.sleep(10);
}
- while (!DockerMock.getRequests().startsWith("startContainer with DockerImage: DockerImage { imageId=dockerImage }, " +
- "HostName: host1, ContainerName: ContainerName { name=container }, InetAddress: null, minCpuCores: 1.0, minDiskAvailableGb: 1.0, " +
- "minMainMemoryAvailableGb: 1.0\nexecuteInContainer with ContainerName: ContainerName { name=container }, " +
- "args: [/usr/bin/env, test, -x, /opt/vespa/bin/vespa-nodectl]\nexecuteInContainer with ContainerName: " +
- "ContainerName { name=container }, args: [/opt/vespa/bin/vespa-nodectl, resume]\n")) {
+ while (!DockerMock.getRequests().startsWith(
+ "createStartContainerCommand with DockerImage: DockerImage { imageId=dockerImage }, HostName: hostName, ContainerName: ContainerName { name=container }\n" +
+ "executeInContainer with ContainerName: ContainerName { name=container }, args: [/usr/bin/env, test, -x, /opt/vespa/bin/vespa-nodectl]\n" +
+ "executeInContainer with ContainerName: ContainerName { name=container }, args: [/opt/vespa/bin/vespa-nodectl, resume]\n")) {
Thread.sleep(10);
}
}
@@ -92,8 +91,7 @@ public class DockerFailTest {
public void dockerFailTest() throws InterruptedException {
dockerMock.deleteContainer(initialContainerNodeSpec.containerName);
- String goal = "startContainer with DockerImage: DockerImage { imageId=dockerImage }, HostName: host1, " +
- "ContainerName: ContainerName { name=container }, InetAddress: null, minCpuCores: 1.0, minDiskAvailableGb: 1.0, minMainMemoryAvailableGb: 1.0\n" +
+ String goal = "createStartContainerCommand with DockerImage: DockerImage { imageId=dockerImage }, HostName: hostName, ContainerName: ContainerName { name=container }\n" +
"executeInContainer with ContainerName: ContainerName { name=container }, args: [/usr/bin/env, test, -x, /opt/vespa/bin/vespa-nodectl]\n" +
"executeInContainer with ContainerName: ContainerName { name=container }, args: [/opt/vespa/bin/vespa-nodectl, resume]\n" +
"deleteContainer with ContainerName: ContainerName { name=container }\n" +
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
index 29af705d44a..aa1c53fd59c 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
@@ -2,13 +2,12 @@
package com.yahoo.vespa.hosted.node.admin.integrationTests;
import com.yahoo.vespa.applicationmodel.HostName;
-import com.yahoo.vespa.hosted.node.admin.docker.Container;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.Docker;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
-import com.yahoo.vespa.hosted.node.admin.docker.ProcessResult;
+import com.yahoo.vespa.hosted.dockerapi.Container;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
-import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -42,15 +41,28 @@ public class DockerMock implements Docker {
}
@Override
- public void startContainer(DockerImage dockerImage, HostName hostName, ContainerName containerName, InetAddress inetAddress,
- double minCpuCores, double minDiskAvailableGb, double minMainMemoryAvailableGb) {
+ public StartContainerCommand createStartContainerCommand(
+ DockerImage dockerImage,
+ ContainerName containerName,
+ HostName hostName) {
synchronized (monitor) {
- requests.append("startContainer with DockerImage: ").append(dockerImage).append(", HostName: ").append(hostName)
- .append(", ContainerName: ").append(containerName).append(", InetAddress: ").append(inetAddress)
- .append(", minCpuCores: ").append(minCpuCores).append(", minDiskAvailableGb: ").append(minDiskAvailableGb)
- .append(", minMainMemoryAvailableGb: ").append(minMainMemoryAvailableGb).append("\n");
+ requests.append("createStartContainerCommand with DockerImage: ")
+ .append(dockerImage).append(", HostName: ").append(hostName)
+ .append(", ContainerName: ").append(containerName).append("\n");
containers.add(new Container(hostName, dockerImage, containerName, true));
}
+
+ return new StartContainerCommandMock();
+ }
+
+ @Override
+ public ContainerInfo inspectContainer(ContainerName containerName) {
+ return new ContainerInfo() {
+ @Override
+ public Optional<Integer> getPid() {
+ return Optional.of(2);
+ }
+ };
}
@Override
@@ -102,11 +114,6 @@ public class DockerMock implements Docker {
}
@Override
- public String getVespaVersion(ContainerName containerName) {
- return null;
- }
-
- @Override
public void deleteImage(DockerImage dockerImage) {
}
@@ -136,5 +143,41 @@ public class DockerMock implements Docker {
requests = new StringBuilder();
}
}
-}
+ public static class StartContainerCommandMock implements StartContainerCommand {
+ @Override
+ public StartContainerCommand withLabel(String name, String value) {
+ return this;
+ }
+
+ @Override
+ public StartContainerCommand withEnvironment(String name, String value) {
+ return this;
+ }
+
+ @Override
+ public StartContainerCommand withVolume(String path, String volumePath) {
+ return this;
+ }
+
+ @Override
+ public StartContainerCommand withMemoryInMb(long megaBytes) {
+ return this;
+ }
+
+ @Override
+ public StartContainerCommand withNetworkMode(String mode) {
+ return this;
+ }
+
+ @Override
+ public StartContainerCommand withIpv6Address(String address) {
+ return this;
+ }
+
+ @Override
+ public void start() {
+
+ }
+ }
+}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MaintenanceSchedulerMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MaintenanceSchedulerMock.java
index a6c4ed63439..c634cd2aa05 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MaintenanceSchedulerMock.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MaintenanceSchedulerMock.java
@@ -1,6 +1,6 @@
package com.yahoo.vespa.hosted.node.admin.integrationTests;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.node.admin.maintenance.MaintenanceScheduler;
import java.io.IOException;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MultiDockerTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MultiDockerTest.java
index da658e462a9..1f776a4b911 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MultiDockerTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/MultiDockerTest.java
@@ -4,8 +4,8 @@ package com.yahoo.vespa.hosted.node.admin.integrationTests;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdmin;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminImpl;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdater;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeRepoMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeRepoMock.java
index ecdcf5e21e6..0e493cf9219 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeRepoMock.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeRepoMock.java
@@ -3,8 +3,8 @@ package com.yahoo.vespa.hosted.node.admin.integrationTests;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeRepository;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeState;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeStateTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeStateTest.java
index 7dc0a449913..af1b447b1d2 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeStateTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/NodeStateTest.java
@@ -3,8 +3,8 @@ package com.yahoo.vespa.hosted.node.admin.integrationTests;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdmin;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminImpl;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdater;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ResumeTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ResumeTest.java
index 229f10bfe64..c7489fc28aa 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ResumeTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/ResumeTest.java
@@ -8,8 +8,8 @@ import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminImpl;
import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdater;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgent;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentImpl;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.nodeagent.DockerOperations;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeState;
import org.junit.After;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminImplTest.java
index 312db45c790..2de470f403c 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminImplTest.java
@@ -4,10 +4,10 @@ package com.yahoo.vespa.hosted.node.admin.nodeadmin;
import com.yahoo.collections.Pair;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.Container;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.Docker;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.Container;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.node.admin.maintenance.MaintenanceScheduler;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgent;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentImpl;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminStateUpdaterTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminStateUpdaterTest.java
index 9c9cdf7b5f7..5b3ce94614c 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminStateUpdaterTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeadmin/NodeAdminStateUpdaterTest.java
@@ -3,7 +3,7 @@ package com.yahoo.vespa.hosted.node.admin.nodeadmin;
import com.yahoo.prelude.semantics.RuleBaseException;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import com.yahoo.vespa.hosted.node.admin.integrationTests.OrchestratorMock;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeRepository;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeState;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/DockerOperationsTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/DockerOperationsTest.java
index c9cd8963617..8f3850dc569 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/DockerOperationsTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/DockerOperationsTest.java
@@ -1,20 +1,25 @@
// 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.nodeagent;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.Docker;
-import com.yahoo.vespa.hosted.node.admin.docker.ProcessResult;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
+import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.mockito.InOrder;
import java.util.Optional;
import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyVararg;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class DockerOperationsTest {
private final Docker docker = mock(Docker.class);
@@ -80,4 +85,39 @@ public class DockerOperationsTest {
assertThat(result.isPresent(), is(true));
assertThat(result.get(), is(actualResult));
}
+
+ @Test
+ public void vespaVersionIsParsed() {
+ assertThat(DockerOperations.parseVespaVersion("5.119.53"), CoreMatchers.is(Optional.of("5.119.53")));
+ }
+
+ @Test
+ public void vespaVersionIsParsedWithSpacesAndNewlines() {
+ assertThat(DockerOperations.parseVespaVersion("5.119.53\n"), CoreMatchers.is(Optional.of("5.119.53")));
+ assertThat(DockerOperations.parseVespaVersion(" 5.119.53 \n"), CoreMatchers.is(Optional.of("5.119.53")));
+ assertThat(DockerOperations.parseVespaVersion("\n 5.119.53 \n"), CoreMatchers.is(Optional.of("5.119.53")));
+ }
+
+ @Test
+ public void vespaVersionIsParsedWithIrregularVersionScheme() {
+ assertThat(DockerOperations.parseVespaVersion("7.2"), CoreMatchers.is(Optional.of("7.2")));
+ assertThat(DockerOperations.parseVespaVersion("8.0-beta"), CoreMatchers.is(Optional.of("8.0-beta")));
+ assertThat(DockerOperations.parseVespaVersion("foo"), CoreMatchers.is(Optional.of("foo")));
+ assertThat(DockerOperations.parseVespaVersion("119"), CoreMatchers.is(Optional.of("119")));
+ }
+
+ @Test
+ public void vespaVersionIsNotParsedFromNull() {
+ assertThat(DockerOperations.parseVespaVersion(null), CoreMatchers.is(Optional.empty()));
+ }
+
+ @Test
+ public void vespaVersionIsNotParsedFromEmptyString() {
+ assertThat(DockerOperations.parseVespaVersion(""), CoreMatchers.is(Optional.empty()));
+ }
+
+ @Test
+ public void vespaVersionIsNotParsedFromUnexpectedContent() {
+ assertThat(DockerOperations.parseVespaVersion("No such command 'vespanodectl'"), CoreMatchers.is(Optional.empty()));
+ }
} \ No newline at end of file
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
index c50d25d5b67..d2d71c7b0be 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
@@ -2,12 +2,13 @@
package com.yahoo.vespa.hosted.node.admin.nodeagent;
import com.yahoo.vespa.applicationmodel.HostName;
+import com.yahoo.vespa.hosted.dockerapi.Container;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.Docker;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.Container;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.Docker;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
-import com.yahoo.vespa.hosted.node.admin.docker.ProcessResult;
+import com.yahoo.vespa.hosted.node.admin.integrationTests.DockerMock;
import com.yahoo.vespa.hosted.node.admin.maintenance.MaintenanceScheduler;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeRepository;
import com.yahoo.vespa.hosted.node.admin.noderepository.NodeState;
@@ -22,7 +23,6 @@ import java.util.concurrent.CompletableFuture;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyVararg;
@@ -76,7 +76,8 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(dockerImage)).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(docker.getContainer(hostName)).thenReturn(Optional.of(existingContainer));
@@ -85,14 +86,10 @@ public class NodeAgentImplTest {
verify(orchestrator, never()).suspend(any(HostName.class));
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker, never()).deleteContainer(any(ContainerName.class));
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(docker, times(1)).executeInContainer(any(), anyVararg());
final InOrder inOrder = inOrder(orchestrator, nodeRepository);
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, restartGeneration, dockerImage, vespaVersion);
@@ -120,12 +117,11 @@ public class NodeAgentImplTest {
final String vespaVersion = "7.8.9";
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(docker.getContainer(hostName)).thenReturn(Optional.of(existingContainer)).thenReturn(Optional.empty());
- ;
-
when(docker.imageIsDownloaded(dockerImage)).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
nodeAgent.tick();
@@ -135,14 +131,10 @@ public class NodeAgentImplTest {
inOrder.verify(docker, times(1)).executeInContainer(any(), anyVararg());
inOrder.verify(docker).stopContainer(containerName);
inOrder.verify(docker).deleteContainer(containerName);
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
inOrder.verify(docker, times(1)).executeInContainer(any(), anyVararg());
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, wantedRestartGeneration, dockerImage, vespaVersion);
@@ -172,7 +164,8 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(wantedDockerImage)).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
when(docker.getContainer(hostName)).thenReturn(Optional.of(existingContainer)).thenReturn(Optional.empty());
@@ -184,14 +177,10 @@ public class NodeAgentImplTest {
inOrder.verify(orchestrator).suspend(hostName);
inOrder.verify(docker).stopContainer(containerName);
inOrder.verify(docker).deleteContainer(containerName);
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
inOrder.verify(docker, times(1)).executeInContainer(any(), anyVararg());
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, restartGeneration, wantedDockerImage, vespaVersion);
inOrder.verify(orchestrator).resume(hostName);
@@ -252,8 +241,13 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(dockerImage)).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
+ when(docker.createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname)).thenReturn(new DockerMock.StartContainerCommandMock());
nodeAgent.tick();
@@ -262,14 +256,10 @@ public class NodeAgentImplTest {
verify(docker, times(1)).executeInContainer(any(), anyVararg());
final InOrder inOrder = inOrder(orchestrator, docker, nodeRepository);
inOrder.verify(docker).deleteContainer(containerName);
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, restartGeneration, dockerImage, vespaVersion);
inOrder.verify(orchestrator).resume(hostName);
}
@@ -294,7 +284,8 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(dockerImage)).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(docker.getContainer(hostName)).thenReturn(Optional.empty());
@@ -306,14 +297,10 @@ public class NodeAgentImplTest {
verify(docker, times(1)).executeInContainer(any(), anyVararg());
verify(orchestrator, never()).suspend(any(HostName.class));
final InOrder inOrder = inOrder(orchestrator, docker, nodeRepository);
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, restartGeneration, dockerImage, vespaVersion);
inOrder.verify(orchestrator).resume(hostName);
}
@@ -351,14 +338,10 @@ public class NodeAgentImplTest {
verify(orchestrator).suspend(hostName);
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker, never()).deleteContainer(any(ContainerName.class));
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -393,14 +376,10 @@ public class NodeAgentImplTest {
final InOrder inOrder = inOrder(orchestrator, docker);
inOrder.verify(docker).stopContainer(containerName);
inOrder.verify(docker).deleteContainer(containerName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -435,14 +414,10 @@ public class NodeAgentImplTest {
verify(orchestrator, never()).suspend(any(HostName.class));
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker).deleteContainer(containerName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -475,14 +450,10 @@ public class NodeAgentImplTest {
verify(orchestrator, never()).suspend(any(HostName.class));
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker, never()).deleteContainer(containerName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -518,14 +489,10 @@ public class NodeAgentImplTest {
final InOrder inOrder = inOrder(orchestrator, docker);
inOrder.verify(docker).stopContainer(containerName);
inOrder.verify(docker).deleteContainer(containerName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -562,14 +529,10 @@ public class NodeAgentImplTest {
verify(orchestrator, never()).suspend(any(HostName.class));
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker).deleteContainer(containerName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -605,14 +568,10 @@ public class NodeAgentImplTest {
verify(orchestrator, never()).suspend(any(HostName.class));
verify(docker, never()).stopContainer(any(ContainerName.class));
verify(docker, never()).deleteContainer(any(ContainerName.class));
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(maintenanceScheduler, never()).deleteContainerStorage(any(ContainerName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
@@ -652,14 +611,10 @@ public class NodeAgentImplTest {
inOrder.verify(docker).deleteContainer(containerName);
inOrder.verify(maintenanceScheduler).deleteContainerStorage(containerName);
inOrder.verify(nodeRepository).markAsReady(hostName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -698,14 +653,10 @@ public class NodeAgentImplTest {
inOrder.verify(docker).deleteContainer(containerName);
inOrder.verify(maintenanceScheduler).deleteContainerStorage(containerName);
inOrder.verify(nodeRepository).markAsReady(hostName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -741,14 +692,10 @@ public class NodeAgentImplTest {
final InOrder inOrder = inOrder(docker, nodeRepository, maintenanceScheduler);
inOrder.verify(maintenanceScheduler).deleteContainerStorage(containerName);
inOrder.verify(nodeRepository).markAsReady(hostName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -785,14 +732,10 @@ public class NodeAgentImplTest {
final InOrder inOrder = inOrder(docker, nodeRepository, maintenanceScheduler);
inOrder.verify(maintenanceScheduler).deleteContainerStorage(containerName);
inOrder.verify(nodeRepository).markAsReady(hostName);
- verify(docker, never()).startContainer(
+ verify(docker, never()).createStartContainerCommand(
any(DockerImage.class),
- any(HostName.class),
any(ContainerName.class),
- any(InetAddress.class),
- anyDouble(),
- anyDouble(),
- anyDouble());
+ any(HostName.class));
verify(orchestrator, never()).resume(any(HostName.class));
verify(nodeRepository, never()).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -831,7 +774,8 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(any(DockerImage.class))).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
final InOrder inOrder = inOrder(nodeRepository, docker);
@@ -908,7 +852,8 @@ public class NodeAgentImplTest {
when(docker.imageIsDownloaded(any(DockerImage.class))).thenReturn(true);
when(docker.executeInContainer(eq(containerName), anyVararg())).thenReturn(NODE_PROGRAM_DOESNT_EXIST);
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
doThrow(new IOException()).doNothing().when(nodeRepository).updateNodeAttributes(
any(HostName.class), anyLong(), any(DockerImage.class), anyString());
@@ -967,7 +912,8 @@ public class NodeAgentImplTest {
.thenReturn(new ProcessResult(0, "node program exists", ""))
.thenReturn(new ProcessResult(0, "node program succeeds 3rd time", ""));
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
final InOrder inOrder = inOrder(orchestrator, docker);
@@ -980,14 +926,10 @@ public class NodeAgentImplTest {
fail("Expected to throw an exception");
} catch (Exception e) {
}
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
inOrder.verify(docker, times(2)).executeInContainer(any(), anyVararg());
inOrder.verifyNoMoreInteractions();
@@ -1064,7 +1006,8 @@ public class NodeAgentImplTest {
.thenReturn(new ProcessResult(0, "output", "")); // resuming succeeds
break;
}
- when(docker.getVespaVersion(containerName)).thenReturn(vespaVersion);
+ when(docker.executeInContainer(eq(containerName), eq(DockerOperations.GET_VESPA_VERSION_COMMAND)))
+ .thenReturn(new ProcessResult(0, vespaVersion, ""));
when(orchestrator.suspend(any(HostName.class))).thenReturn(true);
when(docker.getContainer(hostName)).thenReturn(Optional.of(existingContainer)).thenReturn(Optional.empty());
@@ -1087,14 +1030,10 @@ public class NodeAgentImplTest {
inOrder.verify(docker).stopContainer(containerName);
inOrder.verify(docker).deleteContainer(containerName);
- inOrder.verify(docker).startContainer(
- eq(nodeSpec.wantedDockerImage.get()),
- eq(nodeSpec.hostname),
- eq(nodeSpec.containerName),
- any(InetAddress.class),
- eq(nodeSpec.minCpuCores.get()),
- eq(nodeSpec.minDiskAvailableGb.get()),
- eq(nodeSpec.minMainMemoryAvailableGb.get()));
+ inOrder.verify(docker).createStartContainerCommand(
+ nodeSpec.wantedDockerImage.get(),
+ nodeSpec.containerName,
+ nodeSpec.hostname);
switch (scenario) {
case EXCEPTION:
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
index 5c707c56bc8..16e41d601fb 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/noderepository/NodeRepositoryImplTest.java
@@ -7,8 +7,8 @@ import com.yahoo.application.Networking;
import com.yahoo.application.container.JDisc;
import com.yahoo.vespa.applicationmodel.HostName;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
-import com.yahoo.vespa.hosted.node.admin.docker.DockerImage;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.provision.testutils.ContainerConfig;
import org.junit.After;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/maintenance/MaintainerTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/maintenance/MaintainerTest.java
index 0c46f4876cc..979b23dbfcb 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/maintenance/MaintainerTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/maintenance/MaintainerTest.java
@@ -1,6 +1,6 @@
package com.yahoo.vespa.hosted.node.maintenance;
-import com.yahoo.vespa.hosted.node.admin.docker.ContainerName;
+import com.yahoo.vespa.hosted.dockerapi.ContainerName;
import org.junit.Test;
import static org.junit.Assert.assertEquals;