monasca.api.integration.docker.ITInfluxDBTest.java Source code

Java tutorial

Introduction

Here is the source code for monasca.api.integration.docker.ITInfluxDBTest.java

Source

/*
 * Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
 * 
 * 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 monasca.api.integration.docker;

import com.github.dockerjava.client.DockerClient;
import com.github.dockerjava.client.DockerException;
import com.github.dockerjava.client.NotFoundException;
import com.github.dockerjava.client.model.ContainerCreateResponse;
import com.github.dockerjava.client.model.ExposedPort;
import com.github.dockerjava.client.model.Ports;
import com.sun.jersey.api.client.ClientResponse;

import org.apache.commons.io.filefilter.RegexFileFilter;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.json.JsonPath.from;

@Test(groups = "integration", enabled = true)
public class ITInfluxDBTest {

    private final static String INFLUXDB_IMAGE_NAME = "monasca/api-integ-tests-influxdb";
    private static final String MYSQL_IMAGE_NAME = "monasca/api-integ-tests-mysql";
    private static final String MYSQL_CONTAINER_RUN_CMD = "/usr/bin/mysqld_safe";
    private static final String KAFKA_IMAGE_NAME = "monasca/api-integ-tests-kafka";
    private static final String KAFKA_CONTAINER_RUN_CMD = "/run.sh";
    private static final String DOCKER_IP = "192.168.59.103";
    private static final String DOCKER_PORT = "2375";
    private static final String DOCKER_URL = "http://" + DOCKER_IP + ":" + DOCKER_PORT;
    private static final int MAX_CONNECT_PORT_TRIES = 10000;

    private final static DockerClient dockerClient = new DockerClient(DOCKER_URL);
    private Process apiProcess = null;
    private ContainerCreateResponse influxDBContainer = null;
    private ContainerCreateResponse mysqlContainer = null;
    private ContainerCreateResponse kafkaContainer = null;

    @BeforeClass
    public void setup() throws DockerException, IOException {

        try {

            runKafka();

            runInfluxDB();

            runMYSQL();

            runAPI();

        } catch (Exception e) {

            System.err.println("Failed to setup environment");
            System.err.println(e);
            tearDown();
            System.exit(-1);
        }
    }

    private void runAPI() throws Exception {

        if (!isPortFree(8070)) {
            throw new Exception("port 8070 is not free. Unable to start instance" + " of monasca api");
        }

        String latestShadedJarFileName = getLatestShadedJarFileName();
        System.out.println("Running " + latestShadedJarFileName);

        ProcessBuilder pb = new ProcessBuilder("java", "-cp", "./target/" + latestShadedJarFileName,
                "monasca.api.MonApiApplication", "server", "src/test/resources/mon-api-config.yml");
        File log = new File("mon-api-integration-test.log");
        pb.redirectErrorStream(true);
        pb.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
        apiProcess = pb.start();

        System.out.println("Started " + latestShadedJarFileName);

        waitForPortReady("localhost", 8070);
    }

    private String getLatestShadedJarFileName() {

        File dir = new File("./target");
        FileFilter fileFilter = new RegexFileFilter("^mon-api-0\\.1\\.0-(\\d|\\w)+-(\\d|\\w)+\\.jar");
        File[] files = dir.listFiles(fileFilter);
        if (files.length == 0) {
            System.err.println("Failed to find shaded jar. You must build mon-api before running this "
                    + "test. Try 'mvn clean package'");
            tearDown();
            System.exit(-1);
        }
        System.out.println("Found " + files.length + " jar files");
        File latestFile = files[0];
        for (File file : files) {
            if (file.lastModified() > latestFile.lastModified()) {
                latestFile = file;
            }
        }

        System.out.println(latestFile.getName() + " is the latest jar file");
        return latestFile.getName();

    }

    boolean isPortFree(int port) {

        try (Socket s = new Socket("localhost", port)) {
            return false;
        } catch (Exception e) {
            return true;
        }

    }

    private void waitForPortReady(String host, int port) {

        System.out.println("waiting to connect to host [" + host + "] on port [" + port + "]");

        Socket s = null;
        boolean isPortReady = false;
        int tryCount = 0;
        while (!isPortReady) {

            if (tryCount >= MAX_CONNECT_PORT_TRIES) {
                System.err.println("Failed to connect to host [" + host + "] on port [" + port + "] in " + "["
                        + tryCount + "] tries");
                tearDown();
                System.exit(-1);
            }

            try {
                s = new Socket();
                s.setReuseAddress(true);
                SocketAddress sa = new InetSocketAddress(host, port);
                s.connect(sa, 50000);
                isPortReady = true;
                System.out.println(
                        "Took " + tryCount + " tries to connect to host [" + host + "] on port" + "[" + port + "]");
            } catch (Exception e) {
                tryCount++;
            }
        }

        if (s != null) {
            try {
                s.close();
            } catch (Exception e) {
                System.err.print(e);
            }
        }
    }

    private void runKafka() {

        ClientResponse response = dockerClient.pullImageCmd(KAFKA_IMAGE_NAME).exec();

        final ExposedPort tcp2181 = ExposedPort.tcp(2181);
        final ExposedPort tcp9092 = ExposedPort.tcp(9092);

        waitForCreateContainer(new CreateContainer(KAFKA_IMAGE_NAME) {
            @Override
            void createContainer() {
                kafkaContainer = dockerClient.createContainerCmd(KAFKA_IMAGE_NAME)
                        .withCmd(new String[] { KAFKA_CONTAINER_RUN_CMD, DOCKER_IP })
                        .withExposedPorts(tcp2181, tcp9092).exec();
            }
        });

        Ports portBindings2 = new Ports();
        portBindings2.bind(tcp2181, Ports.Binding(2181));
        portBindings2.bind(tcp9092, Ports.Binding(9092));

        dockerClient.startContainerCmd(kafkaContainer.getId()).withPortBindings(portBindings2).exec();

        waitForPortReady(DOCKER_IP, 2181);
        waitForPortReady(DOCKER_IP, 9092);
    }

    private void runMYSQL() {

        ClientResponse response = dockerClient.pullImageCmd(MYSQL_IMAGE_NAME).exec();

        final ExposedPort tcp3306 = ExposedPort.tcp(3306);

        waitForCreateContainer(new CreateContainer(MYSQL_IMAGE_NAME) {
            @Override
            void createContainer() {

                mysqlContainer = dockerClient.createContainerCmd(MYSQL_IMAGE_NAME)
                        .withCmd(new String[] { MYSQL_CONTAINER_RUN_CMD }).withExposedPorts(tcp3306).exec();
            }
        });

        Ports portBindings1 = new Ports();
        portBindings1.bind(tcp3306, Ports.Binding(3306));

        dockerClient.startContainerCmd(mysqlContainer.getId()).withPortBindings(portBindings1).exec();

        waitForPortReady(DOCKER_IP, 3306);
    }

    private void runInfluxDB() {

        ClientResponse response = dockerClient.pullImageCmd(INFLUXDB_IMAGE_NAME).exec();

        final ExposedPort tcp8083 = ExposedPort.tcp(8083);
        final ExposedPort tcp8086 = ExposedPort.tcp(8086);
        final ExposedPort tcp8090 = ExposedPort.tcp(8090);
        final ExposedPort tcp8099 = ExposedPort.tcp(8099);

        waitForCreateContainer(new CreateContainer(INFLUXDB_IMAGE_NAME) {
            @Override
            void createContainer() {
                influxDBContainer = dockerClient.createContainerCmd(INFLUXDB_IMAGE_NAME)
                        .withExposedPorts(tcp8083, tcp8086, tcp8090, tcp8099).exec();
            }
        });

        Ports portBindings = new Ports();
        portBindings.bind(tcp8083, Ports.Binding(8083));
        portBindings.bind(tcp8086, Ports.Binding(8086));
        portBindings.bind(tcp8090, Ports.Binding(8090));
        portBindings.bind(tcp8099, Ports.Binding(8099));

        dockerClient.startContainerCmd(influxDBContainer.getId()).withPortBindings(portBindings).exec();

        waitForPortReady(DOCKER_IP, 8086);
    }

    @Test
    public void alarmCreateTest() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-1\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").then().assertThat().statusCode(201);

    }

    @Test
    public void alarmDeleteTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-2\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").asString();

        String alarmId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").delete("/v2.0/alarms/" + alarmId).then().assertThat().statusCode(204);

    }

    @Test
    public void alarmHistoryTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-3\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").asString();

        String alarmId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("v2.0/alarms/" + alarmId + "/state-history").then().assertThat()
                .statusCode(200);

    }

    @Test
    public void alarmListTest() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("/v2.0/alarms").then().assertThat().statusCode(200);

    }

    @Test
    public void alarmPatchTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-4\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").asString();

        String alarmId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").body("{}").patch("v2.0/alarms/" + alarmId).then().assertThat().statusCode(200);

    }

    @Test
    public void alarmShowTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-5\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").asString();

        String alarmId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("v2.0/alarms/" + alarmId).then().assertThat().statusCode(200);

    }

    @Test
    public void alarmUpdateTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-6\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\"}")
                .post("/v2.0/alarms").asString();

        String alarmId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"alarm_actions\": " + "[\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], " + ""
                        + "\"ok_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"name\": \"test-alarm-6\", \"description\": \"test-alarm-description\", "
                        + "\"undetermined_actions\": [\"044fa9be-36ef-4e51-a1d9-67ec31734908\"], "
                        + "\"expression\": \"max(cpu_system_perc) > 0 and max(load_avg_1_min{hostname=mini-mon}) > "
                        + "0\", \"severity\": \"low\", \"actions_enabled\":\"true\", " + "\"state\": \"alarm\"}")
                .put("/v2" + ".0/alarms/" + alarmId).then().assertThat().statusCode(200);

    }

    @Test
    public void measurementListTest() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").param("start_time", "1970-01-01T00:00:00Z").param("name", "cpu_system_perc")
                .get("v2.0/metrics/measurements").then().assertThat().statusCode(200);

    }

    @Test
    public void metricCreateTest() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"timestamp\": 0, \"name\": \"test-metric-1\", "
                        + "\"value\": 1234.5678, \"dimensions\": {\"foo\": \"bar\", " + "\"biz\": \"baz\"}}")
                .post("/v2.0/metrics ").then().assertThat().statusCode(204);

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").param("start_time", "1970-01-01T00:00:00Z").param("name", "test-metric-1")
                .get("v2.0/metrics/measurements").then().assertThat().statusCode(200);

    }

    @Test
    public void metricCreateRawTest() {

        long unixTime = System.currentTimeMillis();

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"timestamp\":\"" + unixTime + "\" , " + "\"name\": \"test-metric-2\", "
                        + "\"value\": 1234.5678, \"dimensions\": {\"foo\": \"bar\", " + "\"biz\": \"baz\"}}")
                .post("/v2.0/metrics ").then().assertThat().statusCode(204);

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").param("start_time", "1970-01-01T00:00:00Z").param("name", "test-metric-2")
                .get("v2.0/metrics/measurements").then().assertThat().statusCode(200);

    }

    @Test
    public void metricList() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("/v2.0/metrics").then().assertThat().statusCode(500);

    }

    @Test
    public void metricStatisticsTest() {

        String[] stats = new String[] { "avg", "min", "max", "count", "sum" };

        for (String stat : stats) {
            given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                    "82510970543135").param("start_time", "1970-01-01T00:00:00Z").param("statistics", stat)
                    .param("name", "cpu_system_perc").get("/v2.0/metrics/statistics").then().assertThat()
                    .statusCode(200);
        }

    }

    @Test
    public void notificationCreateTest() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"type\": \"email\", " + ""
                        + "\"name\": \"test-notification-1\", \"address\": \"jdoe@gmail.com\"}")
                .post("/v2" + ".0/notification-methods").then().assertThat().statusCode(201);
    }

    @Test
    public void notificationDeleteTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"type\": \"email\", " + ""
                        + "\"name\": \"test-notification-2\", \"address\": \"jdoe@gmail.com\"}")
                .post("/v2" + ".0/notification-methods").asString();

        String notificationId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").delete("/v2.0/notification-methods/" + notificationId).then().assertThat()
                .statusCode(204);

    }

    @Test
    public void notificationList() {

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("/v2.0/notification-methods").then().assertThat().statusCode(200);

    }

    @Test
    public void notificationShowTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"type\": \"email\", " + ""
                        + "\"name\": \"test-notification-3\", \"address\": \"jdoe@gmail.com\"}")
                .post("/v2" + ".0/notification-methods").asString();

        String notificationId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("/v2.0/notification-methods/" + notificationId).then().assertThat()
                .statusCode(200);

    }

    @Test
    public void notificationUpdateTest() {

        String json = given()
                .headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                        "82510970543135")
                .body("{\"type\": \"email\", " + ""
                        + "\"name\": \"test-notification-4\", \"address\": \"jdoe@gmail.com\"}")
                .post("/v2" + ".0/notification-methods").asString();

        String notificationId = from(json).get("id");

        given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135")
                .body("{\"type\": \"email\", " + ""
                        + "\"name\": \"test-notification-4\", \"address\": \"jsmith@gmail.com\"}")
                .put("/v2" + ".0/notification-methods/" + notificationId).then().assertThat().statusCode(200);

        json = given().headers("Accept", "application/json", "Content-Type", "application/json", "X-Auth-Token",
                "82510970543135").get("/v2.0/notification-methods/" + notificationId).asString();

        String address = from(json).get("address");

        assert (address.equals("jsmith@gmail.com"));

    }

    @AfterClass
    public void tearDown() {

        stopAPI();

        stopMYSQL();

        stopInfluxDB();

        stopKafka();

    }

    private void stopAPI() {
        if (apiProcess != null) {
            apiProcess.destroy();
        }
    }

    private void stopKafka() {
        if (kafkaContainer != null) {
            dockerClient.stopContainerCmd(kafkaContainer.getId()).withTimeout(2).exec();
        }

    }

    private void stopMYSQL() {
        if (mysqlContainer != null) {
            dockerClient.stopContainerCmd(mysqlContainer.getId()).withTimeout(2).exec();
        }

    }

    private void stopInfluxDB() {
        if (influxDBContainer != null) {
            dockerClient.stopContainerCmd(influxDBContainer.getId()).withTimeout(2).exec();
        }

    }

    private static abstract class CreateContainer {

        private String imageName;

        private CreateContainer(String imageName) {
            this.imageName = imageName;
        }

        abstract void createContainer();

        String getImageName() {
            return imageName;
        }

    }

    private void waitForCreateContainer(CreateContainer createContainer) {

        boolean isContainerCreated = false;
        while (!isContainerCreated) {
            try {
                createContainer.createContainer();
                isContainerCreated = true;
            } catch (NotFoundException e) {
                System.out.println("Waiting for image " + createContainer.getImageName() + " to be pulled");
            }
        }
    }
}