diff options
Diffstat (limited to 'node-admin/src/test/java/com')
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; |