cd.go.contrib.elasticagents.dockerswarm.elasticagent.DockerServiceElasticAgentTest.java Source code

Java tutorial

Introduction

Here is the source code for cd.go.contrib.elasticagents.dockerswarm.elasticagent.DockerServiceElasticAgentTest.java

Source

/*
 * Copyright 2016 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cd.go.contrib.elasticagents.dockerswarm.elasticagent;

import cd.go.contrib.elasticagents.dockerswarm.elasticagent.model.JobIdentifier;
import cd.go.contrib.elasticagents.dockerswarm.elasticagent.requests.CreateAgentRequest;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.spotify.docker.client.messages.Volume;
import com.spotify.docker.client.messages.mount.Mount;
import com.spotify.docker.client.messages.swarm.*;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.*;

import static java.lang.String.format;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class DockerServiceElasticAgentTest extends BaseTest {

    private CreateAgentRequest request;

    @Rule
    public ExpectedException thrown = ExpectedException.none();
    private JobIdentifier jobIdentifier;
    private String environment;

    @Before
    public void setUp() throws Exception {
        HashMap<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        jobIdentifier = new JobIdentifier(100L);
        environment = "production";
        request = new CreateAgentRequest("key", properties, environment, jobIdentifier);
    }

    @Test
    public void shouldCreateService() throws Exception {
        DockerService dockerService = DockerService.create(request, createSettings(), docker);
        services.add(dockerService.name());
        assertServiceExist(dockerService.name());
    }

    @Test
    public void shouldCreateServiceForTheJobId() throws Exception {
        DockerService dockerService = DockerService.create(request, createSettings(), docker);
        services.add(dockerService.name());
        assertThat(dockerService.jobIdentifier(), is(jobIdentifier));
    }

    @Test
    public void shouldNotCreateServiceIfTheImageIsNotProvided() throws Exception {
        CreateAgentRequest request = new CreateAgentRequest("key", new HashMap<>(), "environment",
                new JobIdentifier(100L));

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Must provide `Image` attribute.");

        DockerService.create(request, createSettings(), docker);
    }

    @Test
    public void shouldStartServiceWithCorrectLabel() throws Exception {
        DockerService dockerService = DockerService.create(request, createSettings(), docker);
        services.add(dockerService.name());
        assertServiceExist(dockerService.name());

        Service serviceInfo = docker.inspectService(dockerService.name());
        ImmutableMap<String, String> labels = serviceInfo.spec().labels();

        assertThat(labels.get(Constants.JOB_IDENTIFIER_LABEL_KEY), is(jobIdentifier.toJson()));
        assertThat(labels.get(Constants.ENVIRONMENT_LABEL_KEY), is(environment));
        assertThat(labels.get(Constants.CREATED_BY_LABEL_KEY), is(Constants.PLUGIN_ID));
        assertThat(labels.get(Constants.CONFIGURATION_LABEL_KEY), is(new Gson().toJson(request.properties())));
    }

    @Test
    public void shouldStartServiceWithCorrectEnvironment() throws Exception {
        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("Environment", "A=B\nC=D\r\nE=F\n\n\nX=Y");

        PluginSettings settings = createSettings();
        settings.setEnvironmentVariables("GLOBAL=something");
        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), settings, docker);
        services.add(service.name());

        Service serviceInfo = docker.inspectService(service.name());

        assertThat(serviceInfo.spec().taskTemplate().containerSpec().env(),
                hasItems("A=B", "C=D", "E=F", "X=Y", "GLOBAL=something"));
        DockerService dockerService = DockerService.fromService(serviceInfo);

        assertThat(dockerService.properties().get("Environment"), is(properties.get("Environment")));
    }

    @Test
    public void shouldStartContainerWithAutoregisterEnvironmentVariables() throws Exception {
        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());
        Service serviceInfo = docker.inspectService(service.name());
        assertThat(serviceInfo.spec().taskTemplate().containerSpec().env(), hasItem("GO_EA_AUTO_REGISTER_KEY=key"));
        assertThat(serviceInfo.spec().taskTemplate().containerSpec().env(),
                hasItem("GO_EA_AUTO_REGISTER_ENVIRONMENT=prod"));
        assertThat(serviceInfo.spec().taskTemplate().containerSpec().env(),
                hasItem("GO_EA_AUTO_REGISTER_ELASTIC_AGENT_ID=" + service.name()));
        assertThat(serviceInfo.spec().taskTemplate().containerSpec().env(),
                hasItem("GO_EA_AUTO_REGISTER_ELASTIC_PLUGIN_ID=" + Constants.PLUGIN_ID));
    }

    @Test
    public void shouldStartContainerWithCorrectCommand() throws Exception {
        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        List<String> command = Arrays.asList("/bin/sh", "-c", "cat /etc/hosts /etc/group");
        properties.put("Command", StringUtils.join(command, "\n"));

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());
        Service serviceInfo = docker.inspectService(service.name());

        assertThat(serviceInfo.spec().taskTemplate().containerSpec().command(), is(command));
    }

    @Test
    public void shouldStartContainerWithCorrectMemoryLimit() throws Exception {
        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("MaxMemory", "512MB");
        properties.put("ReservedMemory", "100MB");

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());
        Service serviceInfo = docker.inspectService(service.name());
        assertThat(serviceInfo.spec().taskTemplate().resources().limits().memoryBytes(), is(512 * 1024 * 1024L));
        assertThat(serviceInfo.spec().taskTemplate().resources().reservations().memoryBytes(),
                is(100 * 1024 * 1024L));
    }

    @Test
    public void shouldStartContainerWithHostEntry() throws Exception {
        requireDockerApiVersionAtLeast("1.26", "Swarm host entry support");

        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("Hosts", "127.0.0.1 foo bar\n 127.0.0.2 baz");

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());

        final Service inspectServiceInfo = docker.inspectService(service.name());
        assertThat(inspectServiceInfo.spec().taskTemplate().containerSpec().hosts(),
                contains("127.0.0.1 foo", "127.0.0.1 bar", "127.0.0.2 baz"));
    }

    @Test
    public void shouldStartContainerWithMountedVolume() throws Exception {
        requireDockerApiVersionAtLeast("1.26", "Docker volume mount.");

        final String volumeName = UUID.randomUUID().toString();

        final Volume volume = docker.createVolume(Volume.builder().name(volumeName).driver("local")
                .labels(Collections
                        .singletonMap("cd.go.contrib.elasticagents.dockerswarm.elasticagent.DockerPlugin", ""))
                .build());

        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("Mounts", "source=" + volumeName + ", target=/path/in/container");

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());

        final Service inspectServiceInfo = docker.inspectService(service.name());
        final Mount mount = inspectServiceInfo.spec().taskTemplate().containerSpec().mounts().get(0);

        assertThat(mount.source(), is(volumeName));
        assertThat(mount.type(), is("volume"));
    }

    @Test
    public void shouldTerminateAnExistingService() throws Exception {
        DockerService dockerService = DockerService.create(request, createSettings(), docker);
        services.add(dockerService.name());

        dockerService.terminate(docker);

        assertServiceDoesNotExist(dockerService.name());
    }

    @Test
    public void shouldFindAnExistingService() throws Exception {
        DockerService service = DockerService.create(request, createSettings(), docker);
        services.add(service.name());

        DockerService dockerService = DockerService.fromService(docker.inspectService(service.name()));

        assertEquals(service, dockerService);
    }

    @Test
    public void shouldFindAnExistingServiceWithJobIdInformation() throws Exception {
        DockerService service = DockerService.create(request, createSettings(), docker);
        services.add(service.name());
        assertThat(service.jobIdentifier(), is(jobIdentifier));

        DockerService dockerService = DockerService.fromService(docker.inspectService(service.name()));

        assertThat(service.jobIdentifier(), is(jobIdentifier));
        assertEquals(service, dockerService);
    }

    @Test
    public void shouldStartContainerWithSecret() throws Exception {
        requireDockerApiVersionAtLeast("1.26", "Swarm secret support");

        final String secretName = UUID.randomUUID().toString();
        final SecretCreateResponse secret = docker.createSecret(SecretSpec.builder().name(secretName)
                .data(Base64.getEncoder().encodeToString("some-random-junk".getBytes()))
                .labels(Collections
                        .singletonMap("cd.go.contrib.elasticagents.dockerswarm.elasticagent.DockerPlugin", ""))
                .build());

        final List<String> command = Arrays.asList("/bin/sh", "-c", "cat /run/secrets/" + secretName);
        Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("Secrets", "src=" + secretName);
        properties.put("Command", StringUtils.join(command, "\n"));

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());

        final Service inspectService = docker.inspectService(service.name());
        final SecretBind secretBind = inspectService.spec().taskTemplate().containerSpec().secrets().get(0);

        assertThat(secretBind.secretName(), is(secretName));
        assertThat(secretBind.secretId(), is(secret.id()));
    }

    @Test
    public void shouldCreateServiceWithConstraints() throws Exception {
        final List<Node> nodes = docker.listNodes();
        final String nodeId = nodes.get(0).id();
        final Map<String, String> properties = new HashMap<>();
        properties.put("Image", "alpine:latest");
        properties.put("Constraints", format("node.id == %s", nodeId));

        DockerService service = DockerService.create(
                new CreateAgentRequest("key", properties, "prod", new JobIdentifier(100L)), createSettings(),
                docker);
        services.add(service.name());

        final Service inspectService = docker.inspectService(service.name());
        final ImmutableList<String> constraints = inspectService.spec().taskTemplate().placement().constraints();

        assertThat(constraints, contains(format("node.id == %s", nodeId)));
    }
}