org.arquillian.cube.impl.docker.DockerClientExecutor Maven / Gradle / Ivy
package org.arquillian.cube.impl.docker;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ws.rs.ProcessingException;
import org.arquillian.cube.impl.client.CubeConfiguration;
import org.arquillian.cube.impl.util.BindingUtil;
import org.arquillian.cube.impl.util.Boot2Docker;
import org.arquillian.cube.impl.util.HomeResolverUtil;
import org.arquillian.cube.impl.util.IOUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.NotFoundException;
import com.github.dockerjava.api.command.BuildImageCmd;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.command.LogContainerCmd;
import com.github.dockerjava.api.command.PingCmd;
import com.github.dockerjava.api.command.PullImageCmd;
import com.github.dockerjava.api.command.StartContainerCmd;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Capability;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Device;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Link;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.Ports.Binding;
import com.github.dockerjava.api.model.RestartPolicy;
import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.api.model.VolumesFrom;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.DockerClientConfig.DockerClientConfigBuilder;
public class DockerClientExecutor {
private static final String PORTS_SEPARATOR = BindingUtil.PORTS_SEPARATOR;
private static final String TAG_SEPARATOR = ":";
private static final String RESTART_POLICY = "restartPolicy";
private static final String CAP_DROP = "capDrop";
private static final String CAP_ADD = "capAdd";
private static final String DEVICES = "devices";
private static final String DNS_SEARCH = "dnsSearch";
private static final String NETWORK_MODE = "networkMode";
private static final String PUBLISH_ALL_PORTS = "publishAllPorts";
private static final String PRIVILEGED = "privileged";
private static final String PORT_BINDINGS = "portBindings";
private static final String LINKS = "links";
private static final String BINDS = "binds";
private static final String VOLUMES_FROM = "volumesFrom";
private static final String VOLUMES = "volumes";
private static final String DNS = "dns";
private static final String CMD = "cmd";
private static final String ENV = "env";
private static final String EXPOSED_PORTS = "exposedPorts";
private static final String ATTACH_STDERR = "attachStderr";
private static final String ATTACH_STDIN = "attachStdin";
private static final String CPU_SHARES = "cpuShares";
private static final String MEMORY_SWAP = "memorySwap";
private static final String MEMORY_LIMIT = "memoryLimit";
private static final String STDIN_ONCE = "stdinOnce";
private static final String STDIN_OPEN = "stdinOpen";
private static final String TTY = "tty";
private static final String USER = "user";
private static final String PORT_SPECS = "portSpecs";
private static final String HOST_NAME = "hostName";
private static final String DISABLE_NETWORK = "disableNetwork";
private static final String WORKING_DIR = "workingDir";
private static final String IMAGE = "image";
private static final String BUILD_IMAGE = "buildImage";
private static final String DOCKERFILE_LOCATION = "dockerfileLocation";
private static final String NO_CACHE = "noCache";
private static final String REMOVE = "remove";
private static final String FOLLOW = "follow";
private static final String STDOUT = "stdout";
private static final String STDERR = "stderr";
private static final String TIMESTAMPS = "timestamps";
private static final String TAIL = "tail";
private static final String TO = "to";
private static final String FROM = "from";
private static final Logger log = Logger.getLogger(DockerClientExecutor.class.getName());
private static final Pattern IMAGEID_PATTERN = Pattern.compile(".*Successfully built\\s(\\p{XDigit}+)");
private DockerClient dockerClient;
private CubeConfiguration cubeConfiguration;
private final URI dockerUri;
private final String dockerServerIp;
public DockerClientExecutor(CubeConfiguration cubeConfiguration) {
DockerClientConfigBuilder configBuilder =
DockerClientConfig.createDefaultConfigBuilder();
String dockerServerUri = cubeConfiguration.getDockerServerUri();
dockerUri = URI.create(dockerServerUri);
dockerServerIp = cubeConfiguration.getDockerServerIp();
configBuilder.withVersion(cubeConfiguration.getDockerServerVersion()).withUri(dockerUri.toString());
if(cubeConfiguration.getUsername() != null) {
configBuilder.withUsername(cubeConfiguration.getUsername());
}
if(cubeConfiguration.getPassword() != null) {
configBuilder.withPassword(cubeConfiguration.getPassword());
}
if(cubeConfiguration.getEmail() != null) {
configBuilder.withEmail(cubeConfiguration.getEmail());
}
if(cubeConfiguration.getCertPath() != null) {
configBuilder.withDockerCertPath(HomeResolverUtil.resolveHomeDirectoryChar(cubeConfiguration.getCertPath()));
}
this.dockerClient = DockerClientBuilder.getInstance(configBuilder.build()).build();
this.cubeConfiguration = cubeConfiguration;
}
public List listRunningContainers() {
return this.dockerClient.listContainersCmd().exec();
}
public String createContainer(String name, Map containerConfiguration) {
// we check if Docker server is up and correctly configured.
this.pingDockerServer();
String image = getImageName(containerConfiguration);
CreateContainerCmd createContainerCmd = this.dockerClient.createContainerCmd(image);
createContainerCmd.withName(name);
Set allExposedPorts = resolveExposedPorts(containerConfiguration, createContainerCmd);
if (!allExposedPorts.isEmpty()) {
int numberOfExposedPorts = allExposedPorts.size();
createContainerCmd.withExposedPorts(allExposedPorts.toArray(new ExposedPort[numberOfExposedPorts]));
}
if (containerConfiguration.containsKey(WORKING_DIR)) {
createContainerCmd.withWorkingDir(asString(containerConfiguration, WORKING_DIR));
}
if (containerConfiguration.containsKey(DISABLE_NETWORK)) {
createContainerCmd.withDisableNetwork(asBoolean(containerConfiguration, DISABLE_NETWORK));
}
if (containerConfiguration.containsKey(HOST_NAME)) {
createContainerCmd.withHostName(asString(containerConfiguration, HOST_NAME));
}
if (containerConfiguration.containsKey(PORT_SPECS)) {
List portSpecs = asListOfString(containerConfiguration, PORT_SPECS);
createContainerCmd.withPortSpecs(portSpecs.toArray(new String[portSpecs.size()]));
}
if (containerConfiguration.containsKey(USER)) {
createContainerCmd.withUser(asString(containerConfiguration, USER));
}
if (containerConfiguration.containsKey(TTY)) {
createContainerCmd.withTty(asBoolean(containerConfiguration, TTY));
}
if (containerConfiguration.containsKey(STDIN_OPEN)) {
createContainerCmd.withStdinOpen(asBoolean(containerConfiguration, STDIN_OPEN));
}
if (containerConfiguration.containsKey(STDIN_ONCE)) {
createContainerCmd.withStdInOnce(asBoolean(containerConfiguration, STDIN_ONCE));
}
if (containerConfiguration.containsKey(MEMORY_LIMIT)) {
createContainerCmd.withMemoryLimit(asInt(containerConfiguration, MEMORY_LIMIT));
}
if (containerConfiguration.containsKey(MEMORY_SWAP)) {
createContainerCmd.withMemorySwap(asInt(containerConfiguration, MEMORY_SWAP));
}
if (containerConfiguration.containsKey(CPU_SHARES)) {
createContainerCmd.withCpuShares(asInt(containerConfiguration, CPU_SHARES));
}
if (containerConfiguration.containsKey(ATTACH_STDIN)) {
createContainerCmd.withAttachStdin(asBoolean(containerConfiguration, ATTACH_STDIN));
}
if (containerConfiguration.containsKey(ATTACH_STDERR)) {
createContainerCmd.withAttachStderr(asBoolean(containerConfiguration, ATTACH_STDERR));
}
if (containerConfiguration.containsKey(ENV)) {
List env = asListOfString(containerConfiguration, ENV);
env = resolveDockerServerIpInList(env);
createContainerCmd.withEnv(env.toArray(new String[env.size()]));
}
if (containerConfiguration.containsKey(CMD)) {
List cmd = asListOfString(containerConfiguration, CMD);
createContainerCmd.withCmd(cmd.toArray(new String[cmd.size()]));
}
if (containerConfiguration.containsKey(DNS)) {
List dns = asListOfString(containerConfiguration, DNS);
createContainerCmd.withDns(dns.toArray(new String[dns.size()]));
}
if (containerConfiguration.containsKey(VOLUMES)) {
List volumes = asListOfString(containerConfiguration, VOLUMES);
createContainerCmd.withVolumes(toVolumes(volumes));
}
if (containerConfiguration.containsKey(VOLUMES_FROM)) {
List volumesFrom = asListOfString(containerConfiguration, VOLUMES_FROM);
createContainerCmd.withVolumesFrom(toVolumesFrom(volumesFrom));
}
try {
return createContainerCmd.exec().getId();
} catch (NotFoundException e) {
log.warning(String.format(
"Docker Image %s is not on DockerHost and it is going to be automatically pulled.", image));
this.pullImage(image);
return createContainerCmd.exec().getId();
}
}
private List resolveDockerServerIpInList(List envs) {
List resolvedEnv = new ArrayList();
for (String env : envs) {
if(env.contains(CubeConfiguration.DOCKER_SERVER_IP)) {
resolvedEnv.add(env.replaceAll(CubeConfiguration.DOCKER_SERVER_IP, cubeConfiguration.getDockerServerIp()));
} else {
resolvedEnv.add(env);
}
}
return resolvedEnv;
}
private Set resolveExposedPorts(Map containerConfiguration,
CreateContainerCmd createContainerCmd) {
Set allExposedPorts = new HashSet<>();
if (containerConfiguration.containsKey(PORT_BINDINGS)) {
List portBindings = asListOfString(containerConfiguration, PORT_BINDINGS);
Ports assignPorts = assignPorts(portBindings);
Map bindings = assignPorts.getBindings();
Set exposedPorts = bindings.keySet();
allExposedPorts.addAll(exposedPorts);
}
if (containerConfiguration.containsKey(EXPOSED_PORTS)) {
Set exposedPorts = toExposedPorts(asListOfString(containerConfiguration, EXPOSED_PORTS));
allExposedPorts.addAll(exposedPorts);
}
return allExposedPorts;
}
private String getImageName(Map containerConfiguration) {
String image = null;
if (containerConfiguration.containsKey(IMAGE)) {
image = asString(containerConfiguration, IMAGE);
} else {
if (containerConfiguration.containsKey(BUILD_IMAGE)) {
Map params = asMap(containerConfiguration, BUILD_IMAGE);
if (params.containsKey(DOCKERFILE_LOCATION)) {
String dockerfileLocation = asString(params, DOCKERFILE_LOCATION);
image = this.buildImage(dockerfileLocation, params);
} else {
throw new IllegalArgumentException(
"A tar file with Dockerfile on root or a directory with a Dockerfile should be provided.");
}
} else {
throw new IllegalArgumentException(
String.format(
"Current configuration file does not contain %s nor %s parameter and one of both should be provided.",
IMAGE, BUILD_IMAGE));
}
}
return image;
}
public void startContainer(String id, Map containerConfiguration) {
StartContainerCmd startContainerCmd = this.dockerClient.startContainerCmd(id);
if (containerConfiguration.containsKey(BINDS)) {
List binds = asListOfString(containerConfiguration, BINDS);
startContainerCmd.withBinds(toBinds(binds));
}
if (containerConfiguration.containsKey(LINKS)) {
startContainerCmd.withLinks(toLinks(asListOfString(containerConfiguration, LINKS)));
}
if (containerConfiguration.containsKey(PORT_BINDINGS)) {
List portBindings = asListOfString(containerConfiguration, PORT_BINDINGS);
Ports ports = assignPorts(portBindings);
startContainerCmd.withPortBindings(ports);
}
if (containerConfiguration.containsKey(PRIVILEGED)) {
startContainerCmd.withPrivileged(asBoolean(containerConfiguration, PRIVILEGED));
}
if (containerConfiguration.containsKey(PUBLISH_ALL_PORTS)) {
startContainerCmd.withPublishAllPorts(asBoolean(containerConfiguration, PUBLISH_ALL_PORTS));
}
if (containerConfiguration.containsKey(NETWORK_MODE)) {
startContainerCmd.withNetworkMode(asString(containerConfiguration, NETWORK_MODE));
}
if (containerConfiguration.containsKey(DNS_SEARCH)) {
List dnsSearch = asListOfString(containerConfiguration, DNS_SEARCH);
startContainerCmd.withDnsSearch(dnsSearch.toArray(new String[dnsSearch.size()]));
}
if (containerConfiguration.containsKey(DEVICES)) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy