diff --git a/pom.xml b/pom.xml
index ee059b729..36e53d71e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,20 +114,26 @@
1.51
+
+ org.jmockit
+ jmockit
+ ${jmockit.version}
+ test
+
+
junit
junit
4.11
test
-
+
- org.jmockit
- jmockit
- ${jmockit.version}
+ org.skyscreamer
+ jsonassert
+ 1.2.3
test
-
diff --git a/src/main/java/org/jolokia/docker/maven/StartMojo.java b/src/main/java/org/jolokia/docker/maven/StartMojo.java
index 0c0ec528b..6101e7188 100644
--- a/src/main/java/org/jolokia/docker/maven/StartMojo.java
+++ b/src/main/java/org/jolokia/docker/maven/StartMojo.java
@@ -59,18 +59,15 @@ public void executeInternal(DockerAccess docker) throws DockerAccessException, M
checkImage(docker,imageName);
RunImageConfiguration runConfig = imageConfig.getRunConfiguration();
- if (runConfig == null) {
- // It's a data image which needs not to have a runtime configuration
- runConfig = RunImageConfiguration.DEFAULT;
- }
- PortMapping mappedPorts = getPortMapping(runConfig);
- String container = docker.createContainer(imageName,
- runConfig.getCommand(), mappedPorts.getContainerPorts(),
- runConfig.getEnv());
- docker.startContainer(container,
- mappedPorts,
- findContainersForImages(runConfig.getVolumesFrom()), findLinksWithContainerNames(docker,runConfig.getLinks()));
+ PortMapping mappedPorts = getPortMapping(runConfig, project.getProperties());
+
+ ContainerConfig containerConfig = createContainerConfig(imageName, runConfig, mappedPorts.getContainerPorts());
+ String container = docker.createContainer(containerConfig);
+
+ ContainerHostConfig hostConfig = createHostConfig(docker, runConfig, mappedPorts);
+ docker.startContainer(container, hostConfig);
registerContainer(container, imageConfig);
+
info("Created and started container " +
getContainerAndImageDescription(container, imageConfig.getDescription()));
@@ -90,10 +87,36 @@ public void executeInternal(DockerAccess docker) throws DockerAccessException, M
}
}
}
+
+ // visible for testing
+ ContainerConfig createContainerConfig(String imageName, RunImageConfiguration runConfig, Set ports)
+ throws MojoExecutionException {
+ try {
+ return new ContainerConfig(imageName).hostname(runConfig.getHostname()).domainname(runConfig.getDomainname())
+ .user(runConfig.getUser()).workingDir(runConfig.getWorkingDir()).memory(runConfig.getMemory())
+ .memorySwap(runConfig.getMemorySwap()).entrypoint(runConfig.getEntrypoint()).exposedPorts(ports)
+ .environment(runConfig.getEnv()).command(runConfig.getCommand()).bind(runConfig.getBind());
+ }
+ catch (IllegalArgumentException e) {
+ throw new MojoExecutionException(String.format("Failed to create contained configuration for [%s]", imageName), e);
+ }
+ }
- private PortMapping getPortMapping(RunImageConfiguration runConfig) throws MojoExecutionException {
+ // visible for testing
+ ContainerHostConfig createHostConfig(DockerAccess docker, RunImageConfiguration runConfig, PortMapping mappedPorts)
+ throws DockerAccessException, MojoExecutionException {
+ RunImageConfiguration.RestartPolicy restartPolicy = runConfig.getRestartPolicy();
+ return new ContainerHostConfig().bind(runConfig.getBind()).links(findLinksWithContainerNames(docker, runConfig.getLinks()))
+ .portBindings(mappedPorts).privileged(runConfig.getPrivileged()).dns(runConfig.getDns())
+ .dnsSearch(runConfig.getDnsSearch()).volumesFrom(findContainersForImages(runConfig.getVolumesFrom()))
+ .capAdd(runConfig.getCapAdd()).capDrop(runConfig.getCapDrop())
+ .restartPolicy(restartPolicy.getName(), restartPolicy.getRetry());
+ }
+
+ // visible for testing
+ PortMapping getPortMapping(RunImageConfiguration runConfig, Properties properties) throws MojoExecutionException {
try {
- return new PortMapping(runConfig.getPorts(), project.getProperties());
+ return new PortMapping(runConfig.getPorts(), properties);
} catch (IllegalArgumentException exp) {
throw new MojoExecutionException("Cannot parse portmapping",exp);
}
@@ -108,7 +131,8 @@ private List getImagesConfigsInOrder() throws Moj
}
}
- private List findLinksWithContainerNames(DockerAccess docker, List links) throws DockerAccessException {
+ // visible for testing
+ List findLinksWithContainerNames(DockerAccess docker, List links) throws DockerAccessException {
List ret = new ArrayList<>();
for (String[] link : EnvUtil.splitLinks(links)) {
String container = lookupContainer(link[0]);
@@ -120,7 +144,8 @@ private List findLinksWithContainerNames(DockerAccess docker, List findContainersForImages(List images) throws MojoExecutionException {
+ // visible for testing
+ List findContainersForImages(List images) throws MojoExecutionException {
List containers = new ArrayList<>();
if (images != null) {
for (String image : images) {
@@ -177,7 +202,6 @@ public void checkImage(DockerAccess docker,String image) throws DockerAccessExce
private void waitIfRequested(RunImageConfiguration runConfig, PortMapping mappedPorts, DockerAccess docker, String containerId) {
WaitConfiguration wait = runConfig.getWaitConfiguration();
if (wait != null) {
- int maxTime = wait.getTime();
ArrayList checkers = new ArrayList<>();
ArrayList logOut = new ArrayList<>();
if (wait.getUrl() != null) {
diff --git a/src/main/java/org/jolokia/docker/maven/access/ContainerConfig.java b/src/main/java/org/jolokia/docker/maven/access/ContainerConfig.java
new file mode 100644
index 000000000..4331ca22f
--- /dev/null
+++ b/src/main/java/org/jolokia/docker/maven/access/ContainerConfig.java
@@ -0,0 +1,132 @@
+package org.jolokia.docker.maven.access;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.jolokia.docker.maven.util.EnvUtil;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+
+/**
+ * Represents a configuration used to create a container
+ */
+public class ContainerConfig {
+
+ private final String imageName;
+
+ private final JSONObject object = new JSONObject();
+
+ public ContainerConfig(String imageName) {
+ this.imageName = imageName;
+ object.put("Image", imageName);
+ }
+
+ public ContainerConfig bind(List bind) {
+ if (bind != null && !bind.isEmpty()) {
+ JSONObject volumes = new JSONObject();
+ for (String volume : bind) {
+ if (volume.contains(":")) {
+ volume = volume.split(":")[0];
+ }
+ volumes.put(volume, new JSONObject());
+ }
+ object.put("Volumes", volumes);
+ }
+ return this;
+ }
+
+ public ContainerConfig command(String command) {
+ if (command != null) {
+ JSONArray a = new JSONArray();
+ for (String s : EnvUtil.splitWOnSpaceWithEscape(command)) {
+ a.put(s);
+ }
+ object.put("Cmd", a);
+ }
+ return this;
+ }
+
+ public ContainerConfig domainname(String domainname) {
+ add("Domainname", domainname);
+ return this;
+ }
+
+ public ContainerConfig entrypoint(String entrypoint) {
+ if (entrypoint != null) {
+ add("Entrypoint", entrypoint);
+ }
+ return this;
+ }
+
+ public ContainerConfig environment(Map env) throws IllegalArgumentException {
+ if (env != null && env.size() > 0) {
+ JSONArray a = new JSONArray();
+ for (Map.Entry entry : env.entrySet()) {
+ String value = entry.getValue();
+ if (value == null || value.length() == 0) {
+ throw new IllegalArgumentException(String.format("Env variable '%s' must not be null or empty when running %s",
+ entry.getKey(), imageName));
+ }
+ a.put(entry.getKey() + "=" + entry.getValue());
+ }
+ object.put("Env", a);
+ }
+ return this;
+ }
+
+ public ContainerConfig exposedPorts(Set ports) {
+ if (ports != null && ports.size() > 0) {
+ JSONObject exposedPorts = new JSONObject();
+ for (Integer port : ports) {
+ exposedPorts.put(port.toString() + "/tcp", new JSONObject());
+ }
+ object.put("ExposedPorts", exposedPorts);
+ }
+ return this;
+ }
+
+ public String getImageName() {
+ return imageName;
+ }
+
+ public ContainerConfig hostname(String hostname) {
+ add("Hostname", hostname);
+ return this;
+ }
+
+ public ContainerConfig memory(long memory) {
+ if (memory != 0) {
+ object.put("Memory", memory);
+ }
+ return this;
+ }
+
+ public ContainerConfig memorySwap(long memorySwap) {
+ if (memorySwap != 0) {
+ object.put("MemorySwap", memorySwap);
+ }
+ return this;
+ }
+
+ public String toJson() {
+ return object.toString();
+ }
+
+ public ContainerConfig user(String user) {
+ add("User", user);
+ return this;
+ }
+
+ public ContainerConfig workingDir(String workingDir) {
+ add("WorkingDir", workingDir);
+ return this;
+ }
+
+ private void add(String name, String value) {
+ if (value != null) {
+ object.put(name, value);
+ }
+ }
+}
diff --git a/src/main/java/org/jolokia/docker/maven/access/ContainerHostConfig.java b/src/main/java/org/jolokia/docker/maven/access/ContainerHostConfig.java
new file mode 100644
index 000000000..fd063958e
--- /dev/null
+++ b/src/main/java/org/jolokia/docker/maven/access/ContainerHostConfig.java
@@ -0,0 +1,125 @@
+package org.jolokia.docker.maven.access;
+
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+
+/**
+ * Represents a configuration used to start a container
+ */
+public class ContainerHostConfig {
+
+ private final JSONObject object = new JSONObject();
+
+ public ContainerHostConfig bind(List bind) {
+ if (bind != null && !bind.isEmpty()) {
+ JSONArray host = new JSONArray();
+ for (String volume : bind) {
+ if (volume.contains(":")) {
+ host.put(volume);
+ }
+ }
+ object.put("Binds", host);
+ }
+ return this;
+ }
+
+ public ContainerHostConfig capAdd(List capAdd)
+ {
+ if (capAdd != null) {
+ object.put("CapAdd", new JSONArray(capAdd));
+ }
+ return this;
+ }
+
+ public ContainerHostConfig capDrop(List capDrop)
+ {
+ if (capDrop != null) {
+ object.put("CapDrop", new JSONArray(capDrop));
+ }
+ return this;
+ }
+
+ public ContainerHostConfig dns(List dns)
+ {
+ if (dns != null) {
+ object.put("Dns", new JSONArray(dns));
+ }
+ return this;
+ }
+
+ public ContainerHostConfig dnsSearch(List dnsSearch)
+ {
+ if (dnsSearch != null) {
+ object.put("DnsSearch", new JSONArray(dnsSearch));
+ }
+ return this;
+ }
+
+ public ContainerHostConfig links(List links) {
+ if (links != null) {
+ object.put("Links", new JSONArray(links));
+ }
+ return this;
+ }
+
+ public ContainerHostConfig portBindings(PortMapping portMapping) {
+ Map portMap = portMapping.getPortsMap();
+ if (!portMap.isEmpty()) {
+ JSONObject portBindings = new JSONObject();
+ Map bindToMap = portMapping.getBindToMap();
+
+ for (Map.Entry entry : portMap.entrySet()) {
+ Integer port = entry.getKey();
+ Integer hostPort = entry.getValue();
+
+ JSONObject o = new JSONObject();
+ o.put("HostPort", hostPort != null ? hostPort.toString() : "");
+
+ if (bindToMap.containsKey(port)) {
+ o.put("HostIp", bindToMap.get(port));
+ }
+
+ JSONArray array = new JSONArray();
+ array.put(o);
+
+ portBindings.put(port + "/tcp", array);
+ }
+
+ object.put("PortBindings", portBindings);
+ }
+ return this;
+ }
+
+ public ContainerHostConfig privileged(boolean privileged)
+ {
+ object.put("Privileged", privileged);
+ return this;
+ }
+
+ public ContainerHostConfig restartPolicy(String name, int retry)
+ {
+ if (name != null) {
+ JSONObject policy = new JSONObject();
+ policy.put("Name", name);
+ policy.put("MaximumRetryCount", retry);
+
+ object.put("RestartPolicy", policy);
+ }
+ return this;
+ }
+
+ public String toJson() {
+ return object.toString();
+ }
+
+ public ContainerHostConfig volumesFrom(List volumesFrom) {
+ if (volumesFrom != null) {
+ object.put("VolumesFrom", new JSONArray(volumesFrom));
+ }
+ return this;
+ }
+}
diff --git a/src/main/java/org/jolokia/docker/maven/access/DockerAccess.java b/src/main/java/org/jolokia/docker/maven/access/DockerAccess.java
index ef054eea7..47bcded86 100644
--- a/src/main/java/org/jolokia/docker/maven/access/DockerAccess.java
+++ b/src/main/java/org/jolokia/docker/maven/access/DockerAccess.java
@@ -24,14 +24,11 @@ public interface DockerAccess {
/**
* Create a container from the given image.
*
- * @param image the image from which the container should be created
- * @param command an optional command which gets executed when starting the container. might be null.
- * @param ports ports to expose, can be null
- * @param env map with environment variables to use
+ * @param configuration container configuration
* @return the container id
* @throws DockerAccessException if the container could not be created.
*/
- String createContainer(String image, String command, Set ports, Map env) throws DockerAccessException;
+ String createContainer(ContainerConfig configuration) throws DockerAccessException;
/**
* Get the the name of a container for a given container id
@@ -45,12 +42,11 @@ public interface DockerAccess {
/**
* Start a container.
*
- * @param containerId id of container to start
- * @param portMapping port mapping to use. Must not be null.
- * @param volumesFrom mount volumes from the given container id. Can be null.
+ * @param containerId container id
+ * @param configuration container host configuration
* @throws DockerAccessException if the container could not be started.
*/
- void startContainer(String containerId, PortMapping portMapping, List volumesFrom, List links) throws DockerAccessException;
+ void startContainer(String containerId, ContainerHostConfig configuration) throws DockerAccessException;
/**
* Stop a container.
diff --git a/src/main/java/org/jolokia/docker/maven/access/DockerAccessWithHttpClient.java b/src/main/java/org/jolokia/docker/maven/access/DockerAccessWithHttpClient.java
index 79a7bcef4..505d5f1f2 100644
--- a/src/main/java/org/jolokia/docker/maven/access/DockerAccessWithHttpClient.java
+++ b/src/main/java/org/jolokia/docker/maven/access/DockerAccessWithHttpClient.java
@@ -1,19 +1,31 @@
package org.jolokia.docker.maven.access;
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
-import org.apache.http.*;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.*;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.FileEntity;
@@ -21,8 +33,11 @@
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
-import org.jolokia.docker.maven.util.*;
-import org.json.*;
+import org.jolokia.docker.maven.util.ImageName;
+import org.jolokia.docker.maven.util.LogHandler;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
/**
* Implementation using Apache HttpComponents for accessing remotely
@@ -41,7 +56,7 @@
public class DockerAccessWithHttpClient implements DockerAccess {
// Used Docker API
- static private final String DOCKER_API_VERSION = "v1.10";
+ static private final String DOCKER_API_VERSION = "v1.15";
public static final String HEADER_ACCEPT = "Accept";
public static final String HEADER_ACCEPT_ALL = "*/*";
@@ -81,10 +96,13 @@ public boolean hasImage(String image) throws DockerAccessException {
/** {@inheritDoc} */
@Override
- public String createContainer(String image, String command, Set ports, Map env) throws DockerAccessException {
- HttpUriRequest post = newPost(baseUrl + "/containers/create", getContainerConfig(image, ports, command, env));
+ public String createContainer(ContainerConfig configuration) throws DockerAccessException {
+ String createJson = configuration.toJson();
+ log.debug("Container create config: " + createJson);
+
+ HttpUriRequest post = newPost(baseUrl + "/containers/create", createJson);
HttpResponse resp = request(post);
- checkReturnCode("Creating container for image '" + image + "'", resp, 201);
+ checkReturnCode("Creating container for image '" + configuration.getImageName() + "'", resp, 201);
JSONObject json = asJsonObject(resp);
logWarnings(json);
return json.getString("Id");
@@ -101,10 +119,11 @@ public String getContainerName(String id) throws DockerAccessException {
/** {@inheritDoc} */
@Override
- public void startContainer(String containerId, PortMapping portMapping,List volumesFrom, List links)
- throws DockerAccessException {
- HttpUriRequest req = newPost(baseUrl + "/containers/" + encode(containerId) + "/start",
- getStartConfig(portMapping, volumesFrom, links));
+ public void startContainer(String containerId, ContainerHostConfig configuration) throws DockerAccessException {
+ String startJson = configuration.toJson();
+ log.debug("Container start config: " + startJson);
+
+ HttpUriRequest req = newPost(baseUrl + "/containers/" + encode(containerId) + "/start", startJson);
HttpResponse resp = request(req);
checkReturnCode("Starting container with id " + containerId, resp, 204);
}
@@ -365,54 +384,6 @@ private void parsePortSpecAndUpdateMapping(Map portMapping, Ob
}
}
- private String getContainerConfig(String image, Set ports, String command, Map env) {
- JSONObject ret = new JSONObject();
- ret.put("Image", image);
- if (ports != null && ports.size() > 0) {
- JSONObject exposedPorts = new JSONObject();
- for (Integer port : ports) {
- exposedPorts.put(port.toString() + "/tcp", new JSONObject());
- }
- ret.put("ExposedPorts", exposedPorts);
- }
- if (command != null) {
- JSONArray a = new JSONArray();
- for (String s : EnvUtil.splitWOnSpaceWithEscape(command)) {
- a.put(s);
- }
- ret.put("Cmd",a);
- }
- if (env != null && env.size() > 0) {
- JSONArray a = new JSONArray();
- for (Map.Entry entry : env.entrySet()) {
- String value = entry.getValue();
- if (value == null || value.length() == 0) {
- throw new IllegalArgumentException("Env variable '" + entry.getKey() +
- "' must not be null or empty when running " + image);
- }
- a.put(entry.getKey() + "=" + entry.getValue());
- }
- ret.put("Env", a);
- }
- log.debug("Container create config: " + ret.toString());
- return ret.toString();
- }
-
- private String getStartConfig(PortMapping portMapping, List volumesFrom, List links) {
- JSONObject ret = new JSONObject();
- if (portMapping != null && !portMapping.isEmpty()) {
- ret.put("PortBindings", portMapping.toDockerConfig());
- }
- if (volumesFrom != null) {
- ret.put("VolumesFrom", new JSONArray(volumesFrom));
- }
- if (links != null) {
- ret.put("Links", new JSONArray(links));
- }
- log.debug("Container start config: " + ret.toString());
- return ret.toString();
- }
-
// ======================================================================================================
private void dump(HttpResponse resp) {
@@ -468,9 +439,8 @@ private String addRegistry(String url, ImageName name) {
private String addQueryParam(String url, String param, String value) {
if (value != null) {
return url + (url.contains("?") ? "&" : "?") + param + "=" + encode(value);
- } else {
- return url;
- }
+ }
+ return url;
}
private void processPullOrPushResponse(final String image, HttpResponse resp, final String action)
diff --git a/src/main/java/org/jolokia/docker/maven/config/ImageConfiguration.java b/src/main/java/org/jolokia/docker/maven/config/ImageConfiguration.java
index fcec70391..f72409716 100644
--- a/src/main/java/org/jolokia/docker/maven/config/ImageConfiguration.java
+++ b/src/main/java/org/jolokia/docker/maven/config/ImageConfiguration.java
@@ -56,12 +56,13 @@ public String getName() {
return name;
}
- public String getAlias() {
+ @Override
+ public String getAlias() {
return alias;
}
public RunImageConfiguration getRunConfiguration() {
- return run;
+ return (run == null) ? RunImageConfiguration.DEFAULT : run;
}
public BuildImageConfiguration getBuildConfiguration() {
diff --git a/src/main/java/org/jolokia/docker/maven/config/RunImageConfiguration.java b/src/main/java/org/jolokia/docker/maven/config/RunImageConfiguration.java
index eda5d8d65..fdf5b7907 100644
--- a/src/main/java/org/jolokia/docker/maven/config/RunImageConfiguration.java
+++ b/src/main/java/org/jolokia/docker/maven/config/RunImageConfiguration.java
@@ -3,32 +3,101 @@
import java.util.List;
import java.util.Map;
+import org.jolokia.docker.maven.access.ContainerHostConfig;
+import org.jolokia.docker.maven.config.RunImageConfiguration.Builder;
+import org.jolokia.docker.maven.config.RunImageConfiguration.RestartPolicy;
+
+
/**
* @author roland
* @since 02.09.14
*/
public class RunImageConfiguration {
- public static final RunImageConfiguration DEFAULT = new RunImageConfiguration();
+ static final RunImageConfiguration DEFAULT = new RunImageConfiguration();
// Environment variables to set when starting the container. key: variable name, value: env value
/**
* @parameter
*/
- private Map env;
+ private Map env;
+ private boolean privileged;
+
// Command to execute in container
/**
* @parameter
*/
private String command;
+ // container domain name
+ /**
+ * @parameter
+ */
+ private String domainname;
+
+ // container entry point
+ /**
+ * @parameter
+ */
+ private String entrypoint;
+
+ // container hostname
+ /**
+ * @parameter
+ */
+ private String hostname;
+
+ // container user
+ /**
+ * @parameter
+ */
+ private String user;
+
+ // working directory
+ /**
+ * @paramter
+ */
+ private String workingDir;
+
+ // memory in bytes
+ /**
+ * @parameter
+ */
+ private long memory;
+
+ // total memory (swap + ram) in bytes, -1 to disable
+ /**
+ * @parameter
+ */
+ private long memorySwap;
+
// Path to a file where the dynamically mapped properties are written to
/**
* @parameter
*/
private String portPropertyFile;
+ /**
+ * @parameter
+ */
+ private List dns;
+
+ /**
+ * @parameter
+ */
+ private List dnsSearch;
+
+ /**
+ * @parameter
+ */
+ private List capAdd;
+
+ /**
+ * @parameter
+ */
+ private List capDrop;
+
// Port mapping. Can contain symbolic names in which case dynamic
// ports are used
/**
@@ -42,6 +111,11 @@ public class RunImageConfiguration {
*/
private List volumes;
+ /**
+ * @parameter
+ */
+ private List bind;
+
// Links to other container started
/**
* @parameter
@@ -55,24 +129,42 @@ public class RunImageConfiguration {
*/
private WaitConfiguration wait;
- public RunImageConfiguration() {}
+ /**
+ * @parameter
+ */
+ private RestartPolicy restartPolicy;
- RunImageConfiguration(Map env, String command, String portPropertyFile,
- List ports, List volumes, List links,
- WaitConfiguration wait) {
- this.env = env;
- this.command = command;
- this.portPropertyFile = portPropertyFile;
- this.ports = ports;
- this.volumes = volumes;
- this.links = links;
- this.wait = wait;
+ public RunImageConfiguration() {
}
public Map getEnv() {
return env;
}
+ public String getEntrypoint() {
+ return entrypoint;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public String getDomainname() {
+ return domainname;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public long getMemory() {
+ return memory;
+ }
+
+ public long getMemorySwap() {
+ return memorySwap;
+ }
+
public List getPorts() {
return ports;
}
@@ -85,10 +177,34 @@ public String getPortPropertyFile() {
return portPropertyFile;
}
+ public String getWorkingDir() {
+ return workingDir;
+ }
+
public WaitConfiguration getWaitConfiguration() {
return wait;
}
+ public List getBind() {
+ return bind;
+ }
+
+ public List getCapAdd() {
+ return capAdd;
+ }
+
+ public List getCapDrop() {
+ return capDrop;
+ }
+
+ public List getDns() {
+ return dns;
+ }
+
+ public List getDnsSearch() {
+ return dnsSearch;
+ }
+
public List getVolumesFrom() {
return volumes;
}
@@ -97,55 +213,156 @@ public List getLinks() {
return links;
}
- // ======================================================================================
+ public boolean getPrivileged() {
+ return privileged;
+ }
+
+ public RunImageConfiguration.RestartPolicy getRestartPolicy() {
+ return (restartPolicy == null) ? RestartPolicy.DEFAULT : restartPolicy;
+ }
+
+// ======================================================================================
public static class Builder {
- private Map env;
- private String command;
- private String portPropertyFile;
- private List ports;
- private List volumes;
- private List links;
- private WaitConfiguration wait;
+ private RunImageConfiguration config = new RunImageConfiguration();
public Builder env(Map env) {
- this.env = env;
+ config.env = env;
return this;
}
public Builder command(String command) {
- this.command = command;
+ config.command = command;
+ return this;
+ }
+
+ public Builder domainname(String domainname) {
+ config.domainname = domainname;
+ return this;
+ }
+
+ public Builder entrypoint(String entrypoint) {
+ config.entrypoint = entrypoint;
+ return this;
+ }
+
+ public Builder hostname(String hostname) {
+ config.hostname = hostname;
return this;
}
public Builder portPropertyFile(String portPropertyFile) {
- this.portPropertyFile = portPropertyFile;
+ config.portPropertyFile = portPropertyFile;
+ return this;
+ }
+
+ public Builder workingDir(String workingDir) {
+ config.workingDir = workingDir;
+ return this;
+ }
+
+ public Builder user(String user) {
+ config.user = user;
return this;
}
+ public Builder memory(long memory) {
+ config.memory = memory;
+ return this;
+ }
+
+ public Builder memorySwap(long memorySwap) {
+ config.memorySwap = memorySwap;
+ return this;
+ }
+
+ public Builder bind(List bind) {
+ config.bind = bind;
+ return this;
+ }
+
+ public Builder capAdd(List capAdd) {
+ config.capAdd = capAdd;
+ return this;
+ }
+
+ public Builder capDrop(List capDrop) {
+ config.capDrop = capDrop;
+ return this;
+ }
+
+ public Builder dns(List dns) {
+ config.dns = dns;
+ return this;
+ }
+
+ public Builder dnsSearch(List dnsSearch) {
+ config.dnsSearch = dnsSearch;
+ return this;
+ }
+
public Builder ports(List ports) {
- this.ports = ports;
+ config.ports = ports;
return this;
}
public Builder volumes(List volumes) {
- this.volumes = volumes;
+ config.volumes = volumes;
return this;
}
public Builder links(List links) {
- this.links = links;
+ config.links = links;
return this;
}
public Builder wait(WaitConfiguration wait) {
- this.wait = wait;
+ config.wait = wait;
return this;
}
+ public Builder privileged(boolean privileged) {
+ config.privileged = privileged;
+ return this;
+ }
+
+ public Builder restartPolicy(RestartPolicy restartPolicy) {
+ config.restartPolicy = restartPolicy;
+ return this;
+ }
+
public RunImageConfiguration build() {
- return new RunImageConfiguration(env, command, portPropertyFile, ports,
- volumes, links, wait);
+ return config;
+ }
+ }
+
+ public static class RestartPolicy {
+
+ private static final RestartPolicy DEFAULT = new RestartPolicy();
+
+ /**
+ * @parameter
+ */
+ private String name;
+
+ /**
+ * @parameter
+ */
+ private int retry;
+
+ public RestartPolicy() {}
+
+ public RestartPolicy(String name, int retry) {
+ this.name = name;
+ this.retry = retry;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getRetry() {
+ return retry;
}
}
}
diff --git a/src/test/java/org/jolokia/docker/maven/StartMojoContainerConfigsTest.java b/src/test/java/org/jolokia/docker/maven/StartMojoContainerConfigsTest.java
new file mode 100644
index 000000000..a54daf7fe
--- /dev/null
+++ b/src/test/java/org/jolokia/docker/maven/StartMojoContainerConfigsTest.java
@@ -0,0 +1,125 @@
+package org.jolokia.docker.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.jolokia.docker.maven.access.ContainerConfig;
+import org.jolokia.docker.maven.access.ContainerHostConfig;
+import org.jolokia.docker.maven.access.DockerAccess;
+import org.jolokia.docker.maven.access.DockerAccessException;
+import org.jolokia.docker.maven.access.PortMapping;
+import org.jolokia.docker.maven.config.RunImageConfiguration;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+
+public class StartMojoContainerConfigsTest {
+
+ private static final String BIND = "/tmp:/tmp";
+
+ @Test
+ @SuppressWarnings("unused")
+ public void testCreateContainerAllConfig() throws Exception {
+ /*-
+ * this is really two tests in one
+ * - verify the start mojo calls all the methods to build the container configs
+ * - the container configs produce the correct json when all options are specified
+ *
+ * it didn't seem worth the effor to build a separate test to verify the json and then mock/verify all the calls here
+ */
+ final RunImageConfiguration runConfig =
+ new RunImageConfiguration.Builder().hostname("hostname").domainname("domain.com").user("user").memory(1).memorySwap(1)
+ .env(env()).command("date").entrypoint("entrypoint").bind(bind()).workingDir("/foo").ports(ports()).links(links())
+ .volumes(volumesFrom()).dns(dns()).dnsSearch(dnsSearch()).privileged(true).capAdd(capAdd()).capDrop(capDrop())
+ .restartPolicy(restartPolicy()).build();
+
+ StartMojo mojo = new StartMojo() {
+ @Override
+ List findContainersForImages(List images) throws MojoExecutionException {
+ return images;
+ }
+
+ @Override
+ List findLinksWithContainerNames(DockerAccess docker, List links) throws DockerAccessException {
+ return links;
+ }
+ };
+
+ PortMapping portMapping = mojo.getPortMapping(runConfig, new Properties());
+
+ ContainerConfig config = mojo.createContainerConfig("base", runConfig, portMapping.getContainerPorts());
+ ContainerHostConfig hostConfig = mojo.createHostConfig(null, runConfig, portMapping);
+
+ String expectedConfig = loadFile("docker/createContainerAll.json");
+ JSONAssert.assertEquals(expectedConfig, config.toJson(), true);
+
+ String expectedHostConfig = loadFile("docker/createHostConfigAll.json");
+ JSONAssert.assertEquals(expectedHostConfig, hostConfig.toJson(), true);
+ }
+
+ private List bind() {
+ return Arrays.asList(BIND);
+ }
+
+ private List capAdd() {
+ return Arrays.asList("NET_ADMIN");
+ }
+
+ private List capDrop() {
+ return Arrays.asList("MKNOD");
+ }
+
+ private List dns() {
+ return Arrays.asList("8.8.8.8");
+ }
+
+ private List dnsSearch() {
+ return Arrays.asList("domain.com");
+ }
+
+ private Map env() {
+ Map env = new HashMap<>();
+ env.put("foo", "bar");
+
+ return env;
+ }
+
+ private List links() {
+ return Arrays.asList("redis3:redis");
+ }
+
+ private String loadFile(String fileName) {
+ StringBuilder buffer = new StringBuilder();
+ File file = new File(getClass().getClassLoader().getResource(fileName).getFile());
+
+ try (Scanner scanner = new Scanner(file)) {
+ while (scanner.hasNextLine()) {
+ buffer.append(scanner.nextLine());
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return buffer.toString();
+ }
+
+ private List ports() {
+ return Arrays.asList("0.0.0.0:11022:22");
+ }
+
+ private RunImageConfiguration.RestartPolicy restartPolicy() {
+ return new RunImageConfiguration.RestartPolicy("on-failure", 1);
+ }
+
+ private List volumesFrom() {
+ return Arrays.asList("parent", "other:ro");
+ }
+}
diff --git a/src/test/resources/docker/createContainerAll.json b/src/test/resources/docker/createContainerAll.json
new file mode 100644
index 000000000..47e60319b
--- /dev/null
+++ b/src/test/resources/docker/createContainerAll.json
@@ -0,0 +1,14 @@
+{
+ "Hostname": "hostname",
+ "Domainname": "domain.com",
+ "User": "user",
+ "Memory": 1,
+ "MemorySwap": 1,
+ "Env": [ "foo=bar" ],
+ "Cmd": [ "date" ],
+ "Entrypoint": "entrypoint",
+ "Image": "base",
+ "Volumes": { "/tmp": { } },
+ "WorkingDir": "/foo",
+ "ExposedPorts": { "22/tcp": { } }
+}
\ No newline at end of file
diff --git a/src/test/resources/docker/createHostConfigAll.json b/src/test/resources/docker/createHostConfigAll.json
new file mode 100644
index 000000000..8b63d4a53
--- /dev/null
+++ b/src/test/resources/docker/createHostConfigAll.json
@@ -0,0 +1,12 @@
+{
+ "Binds": [ "/tmp:/tmp" ],
+ "Links": [ "redis3:redis" ],
+ "PortBindings": { "22/tcp": [ { "HostIp" : "0.0.0.0", "HostPort": "11022" }] },
+ "Privileged":true,
+ "Dns": ["8.8.8.8"],
+ "DnsSearch": ["domain.com"],
+ "VolumesFrom": [ "parent", "other:ro" ],
+ "CapAdd": ["NET_ADMIN"],
+ "CapDrop": ["MKNOD"],
+ "RestartPolicy": { "Name": "on-failure", "MaximumRetryCount": 1 }
+}
\ No newline at end of file