de.cebitec.guava.dockertest.Docker.java Source code

Java tutorial

Introduction

Here is the source code for de.cebitec.guava.dockertest.Docker.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.cebitec.guava.dockertest;

import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;

import com.github.dockerjava.client.DockerClient;
import com.github.dockerjava.client.model.Bind;
import com.github.dockerjava.client.model.ContainerCreateResponse;
import com.github.dockerjava.client.model.Image;
import com.github.dockerjava.client.model.Volume;
import com.sun.jersey.api.client.ClientResponse;
//import com.sun.jersey.api.client.ClientResponse;

public class Docker {

    private final DockerClient dockerClient;
    private List<String> envs;

    private static final Logger logger = Logger.getLogger(Docker.class.getName());

    private List<Bind> binds;
    private String repo;
    private List<String> cmd;
    private String outputFile;

    public Docker(String serverUrl) {
        dockerClient = new DockerClient(serverUrl);
        binds = new ArrayList<>();
        cmd = new ArrayList<>();
        repo = "";
        outputFile = "";
    }

    private void pullImage(String repo) throws Exception {
        ClientResponse response = dockerClient.pullImageCmd(repo).exec();

        try (InputStream inputstream = response.getEntityInputStream()) {
            int data = inputstream.read();
            char c;
            String out = "";
            while (data != -1) {
                c = (char) data;
                data = inputstream.read();
                out += c;
            }
        }

        int status = response.getStatusInfo().getStatusCode();

        if (status != 200) {
            throw new Exception("Image can not be pulled.");
        }
        logger.info("pulling image");
    }

    public Docker createContainer(String repo) throws Exception {
        this.repo = repo;
        return this;
    }

    public Docker addVolume(String volume, boolean isReadOnly) {
        if (!binds.contains(new Bind(volume, new Volume(volume), isReadOnly))) {
            binds.add(new Bind(volume, new Volume(volume), isReadOnly));
        }
        return this;
    }

    public Docker addCmd(String cmd) {
        if (!cmd.replaceAll("\\s", "").isEmpty()) {
            this.cmd.add(cmd);
        }
        return this;
    }

    public Docker addEnv(String env) {
        envs.add(env);
        return this;
    }

    public Docker addOutputFile(String outputFile) {
        this.outputFile = outputFile;
        return this;
    }

    public int run() throws Exception {

        if (repo.equals("")) {
            throw new Exception("No container defined.");
        }
        if (!isImageAvailable(repo)) {
            pullImage(repo);
        }

        String[] command = cmd.toArray(new String[cmd.size()]);
        ContainerCreateResponse containerResp = dockerClient.createContainerCmd(repo).withCmd(command).exec();

        if (binds.isEmpty()) {
            dockerClient.startContainerCmd(containerResp.getId()).exec();
        } else {

            dockerClient.startContainerCmd(containerResp.getId()).withBinds(binds.toArray(new Bind[binds.size()]))
                    .exec();
        }

        int exit = dockerClient.waitContainerCmd(containerResp.getId()).exec();

        if (exit != 0) {

            ClientResponse resp = dockerClient.logContainerCmd(containerResp.getId()).withStdErr().exec();
            LineIterator itr = IOUtils.lineIterator(resp.getEntityInputStream(), "US-ASCII");
            while (itr.hasNext()) {
                String line = itr.next();
                //ugly hack because of java -docker bug
                System.out.println(line.replaceAll("[^\\x20-\\x7e]", ""));
                System.out.println(itr.hasNext() ? "\n" : "");
            }

            throw new Exception("Command Exited with code " + exit);
        }
        if (!this.outputFile.isEmpty()) {
            new File(new File(this.outputFile).getParent()).mkdirs();
            PrintWriter writer = new PrintWriter(this.outputFile, "UTF-8");
            ClientResponse resp = dockerClient.logContainerCmd(containerResp.getId()).withStdOut().exec();

            try {
                LineIterator itr = IOUtils.lineIterator(resp.getEntityInputStream(), "UTF-8");
                while (itr.hasNext()) {
                    String out = itr.next();
                    //ugly hack because of java -docker bug
                    out = out.replaceAll("[\\p{Cc}&&[^\t]]", "");
                    writer.write(out);
                    writer.write(itr.hasNext() ? "\n" : "");
                }
            } finally {
                writer.close();
                IOUtils.closeQuietly(resp.getEntityInputStream());
            }
        }
        dockerClient.removeContainerCmd(containerResp.getId()).exec();

        return exit;
    }

    private boolean isImageAvailable(String repo) {
        List<Image> images = dockerClient.listImagesCmd().withShowAll(true).exec();
        for (Image image : images) {
            for (String tag : image.getRepoTags()) {
                if (tag.startsWith(repo)) {
                    return true;
                }
            }
        }
        return false;
    }
}