From 887a1120e5d3c54afa51e84f360ca6740d9916ec Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 30 Mar 2014 10:34:34 +0100 Subject: [PATCH 01/34] redirect JUL logging to SLF4J so we can avoid logging binary to the console when using ADD in Dockerfile --- pom.xml | 6 ++++++ src/main/java/com/kpelykh/docker/client/DockerClient.java | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7929bcb3..4938aa64 100644 --- a/pom.xml +++ b/pom.xml @@ -138,6 +138,12 @@ ${slf4j-api.version} + + org.slf4j + jul-to-slf4j + ${slf4j-api.version} + + ch.qos.logback diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index d29d28ee..d3b8b440 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -8,7 +8,6 @@ import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; @@ -69,7 +68,6 @@ public DockerClient(String serverUrl) { //client = new UnixSocketClient(clientConfig); client.addFilter(new JsonClientFilter()); - client.addFilter(new LoggingFilter()); } /** From 202ba5cc79f0f11f2d92f919bd4a645a9fbb3484 Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 30 Mar 2014 18:52:40 +0100 Subject: [PATCH 02/34] start client with name --- .../com/kpelykh/docker/client/DockerClient.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index d3b8b440..37fe36df 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -381,9 +381,20 @@ public void startContainer(String containerId) throws DockerException { this.startContainer(containerId, null); } - public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException { + public void startContainer(String containerId, HostConfig hostConfig) throws DockerException { + startContainer(containerId, hostConfig, null); + } + + /** + * @param name The name to assign to the container, e.g to user for linking. + */ + public void startContainer(String containerId, HostConfig hostConfig, String name) throws DockerException { + + final String path = name == null ? + String.format("/containers/%s/start", containerId): + String.format("/containers/%s/start?name=%s", containerId, name); - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); + WebResource webResource = client.resource(restEndpointUrl + path); try { LOGGER.trace("POST: {}", webResource); From cd4e37c0f159467f76060b626a07149db1e2d11d Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 30 Mar 2014 19:19:37 +0100 Subject: [PATCH 03/34] Revert "start client with name" This reverts commit 202ba5cc79f0f11f2d92f919bd4a645a9fbb3484. --- .../com/kpelykh/docker/client/DockerClient.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 37fe36df..d3b8b440 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -381,20 +381,9 @@ public void startContainer(String containerId) throws DockerException { this.startContainer(containerId, null); } - public void startContainer(String containerId, HostConfig hostConfig) throws DockerException { - startContainer(containerId, hostConfig, null); - } - - /** - * @param name The name to assign to the container, e.g to user for linking. - */ - public void startContainer(String containerId, HostConfig hostConfig, String name) throws DockerException { - - final String path = name == null ? - String.format("/containers/%s/start", containerId): - String.format("/containers/%s/start?name=%s", containerId, name); + public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException { - WebResource webResource = client.resource(restEndpointUrl + path); + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); try { LOGGER.trace("POST: {}", webResource); From 3bcd138a00a3e01b58fc1feeeb68bba24f6ca16e Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 30 Mar 2014 19:27:23 +0100 Subject: [PATCH 04/34] fixed bug where tag was being ignored --- src/main/java/com/kpelykh/docker/client/DockerClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index d3b8b440..d0908d8d 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -672,7 +672,7 @@ public ClientResponse build(File dockerFolder) throws DockerException { } public ClientResponse build(File dockerFolder, String tag) throws DockerException { - return this.build(dockerFolder, null, false); + return this.build(dockerFolder, tag, false); } public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException { From e36ab13449729ba062c04f8819229018c32d7f5b Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 1 Apr 2014 13:42:20 +0200 Subject: [PATCH 05/34] Fix Broken Test. The Docker File "ADD" command was in lowercase --- src/test/resources/testAddFile/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/testAddFile/Dockerfile b/src/test/resources/testAddFile/Dockerfile index 6efbf091..2900a5e7 100644 --- a/src/test/resources/testAddFile/Dockerfile +++ b/src/test/resources/testAddFile/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu # Copy testrun.sh files into the container -add ./testrun.sh /tmp/ +ADD ./testrun.sh /tmp/ -run cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh +RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh CMD ["testrun.sh"] From e06bcede9bc5333d78f4aa3f94df7bae3c28408d Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 1 Apr 2014 13:44:20 +0200 Subject: [PATCH 06/34] Bix Broken Test. On The build method, the "ADD" files step has a white space in "ADD ". --- src/main/java/com/kpelykh/docker/client/DockerClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 4981893f..ce6b8a68 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -643,7 +643,7 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder); for (String cmd : dockerFileContent) { - if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD ")) { + if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD")) { String addArgs[] = StringUtils.split(cmd, " \t"); if (addArgs.length != 3) { throw new DockerException(String.format("Wrong format on line [%s]", cmd)); From 50bc1ebff0103f7aeb6a5b7b0c40d0817da79f6f Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 1 Apr 2014 13:45:07 +0200 Subject: [PATCH 07/34] Add "ExecutionDriver" Field --- .../java/com/kpelykh/docker/client/model/Info.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/kpelykh/docker/client/model/Info.java b/src/main/java/com/kpelykh/docker/client/model/Info.java index 30667029..f62d6ec3 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -62,6 +62,9 @@ public class Info { @JsonProperty("SwapLimit") private int swapLimit; + + @JsonProperty("ExecutionDriver") + private String executionDriver; public boolean isDebug() { return debug; @@ -191,6 +194,14 @@ public void setSwapLimit(int swapLimit) { this.swapLimit = swapLimit; } + public String getExecutionDriver() { + return executionDriver; + } + + public void setExecutionDriver(String executionDriver) { + this.executionDriver = executionDriver; + } + @Override public String toString() { return "Info{" + From bc086b1cac09eb81a811e90dac775a419a01a103 Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 1 Apr 2014 13:45:27 +0200 Subject: [PATCH 08/34] Add "OnBuild" field --- .../docker/client/model/ContainerConfig.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java index ff7ffc4e..8118ab74 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -37,6 +37,8 @@ public class ContainerConfig { @JsonProperty("Domainname") private String domainName = ""; // FIXME Is this the right type? -BJE @JsonProperty("ExposedPorts") private Map exposedPorts; + + @JsonProperty("OnBuild") private int[] onBuild; public Map getExposedPorts() { return exposedPorts; @@ -241,6 +243,19 @@ public ContainerConfig setEntrypoint(String[] entrypoint) { this.entrypoint = entrypoint; return this; } + + public void setOnBuild(int[] onBuild) { + this.onBuild = onBuild; + } + + public int[] getOnBuild() { + return onBuild; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + @Override public String toString() { @@ -268,6 +283,7 @@ public String toString() { ", privileged=" + privileged + ", workingDir='" + workingDir + '\'' + ", domainName='" + domainName + '\'' + + ", onBuild='" + onBuild + '\'' + '}'; } } From 76100d091abfce5e6ac880c6de4fe0252c76e37f Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 1 Apr 2014 13:46:32 +0200 Subject: [PATCH 09/34] Ignore test-output --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 86139491..8f1fdc77 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ target # Ignore all log files *.log + +#Ignore Test Output +test-output \ No newline at end of file From d5f962d29fe1744179aeb9d145ace020af52ff5c Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sat, 12 Apr 2014 16:57:42 +0100 Subject: [PATCH 10/34] deleted unused files --- .../docker/client/NotFoundException.java | 6 - .../docker/client/UnixSocketClient.java | 12 - .../client/UnixSocketClientHandler.java | 213 ------------------ .../client/UnixSocketSessionInputBuffer.java | 23 -- .../client/UnixSocketSessionOutputBuffer.java | 17 -- .../docker/client/test/DockerClientTest.java | 11 +- 6 files changed, 10 insertions(+), 272 deletions(-) delete mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketClient.java delete mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java delete mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java delete mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java diff --git a/src/main/java/com/kpelykh/docker/client/NotFoundException.java b/src/main/java/com/kpelykh/docker/client/NotFoundException.java index f6c8fe54..76569f7b 100644 --- a/src/main/java/com/kpelykh/docker/client/NotFoundException.java +++ b/src/main/java/com/kpelykh/docker/client/NotFoundException.java @@ -6,15 +6,9 @@ * @author Ryan Campbell ryan.campbell@gmail.com */ public class NotFoundException extends DockerException { - public NotFoundException() { - - } public NotFoundException(String message) { super(message); } - public NotFoundException(String message, Throwable cause) { - super(message, cause); - } } diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java deleted file mode 100644 index 75582037..00000000 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.kpelykh.docker.client; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.config.ClientConfig; - - -public class UnixSocketClient extends Client { - - public UnixSocketClient(ClientConfig clientConfig) { - super(new UnixSocketClientHandler(), clientConfig); - } -} diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java deleted file mode 100644 index 6ce3f1ce..00000000 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java +++ /dev/null @@ -1,213 +0,0 @@ -package com.kpelykh.docker.client; - -import com.sun.jersey.api.client.*; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.core.header.InBoundHeaders; -import com.sun.jersey.core.util.ReaderWriter; -import jnr.unixsocket.UnixSocketAddress; -import jnr.unixsocket.UnixSocketChannel; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpException; -import org.apache.http.HttpResponse; -import org.apache.http.annotation.NotThreadSafe; -import org.apache.http.client.methods.*; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.BufferedHttpEntity; -import org.apache.http.impl.DefaultHttpResponseFactory; -import org.apache.http.impl.io.DefaultHttpResponseParser; -import org.apache.http.impl.io.HttpRequestWriter; -import org.apache.http.message.BasicLineFormatter; -import org.apache.http.message.BasicLineParser; -import org.apache.http.params.BasicHttpParams; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.net.URI; -import java.nio.channels.Channels; -import java.util.ArrayList; -import java.util.List; - -/** - * TODO: Make thread-safe. - */ -@NotThreadSafe -public class UnixSocketClientHandler extends RequestWriter implements ClientHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(UnixSocketClientHandler.class); - - public static final int BUFFERSIZE = 1024; - public static final String DOCKER_SOCKET_PATH = "/var/run/docker.sock"; - - @Override - public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { - try { - File path = new File(DOCKER_SOCKET_PATH); - UnixSocketAddress address = new UnixSocketAddress(path); - UnixSocketChannel channel = UnixSocketChannel.open(address); - OutputStream unixSocketChannelOutputStream = Channels.newOutputStream(channel); - - final HttpUriRequest request = getUriHttpRequest(cr); - BasicHttpParams params = new BasicHttpParams(); - - UnixSocketSessionOutputBuffer outputBuffer = new UnixSocketSessionOutputBuffer(); - outputBuffer.init(unixSocketChannelOutputStream, BUFFERSIZE, params); - HttpRequestWriter writer = new HttpRequestWriter(outputBuffer, new BasicLineFormatter(), params); - writer.write(request); - outputBuffer.flush(); - - UnixSocketSessionInputBuffer inputBuffer = new UnixSocketSessionInputBuffer(); - inputBuffer.init(Channels.newInputStream(channel), BUFFERSIZE, params); - - HttpResponse response = new DefaultHttpResponseParser(inputBuffer, new BasicLineParser(), new DefaultHttpResponseFactory(), params).parse(); - LOGGER.trace(response.toString()); - - ClientResponse clientResponse = new ClientResponse(response.getStatusLine().getStatusCode(), - getInBoundHeaders(response), - new HttpClientResponseInputStream(response), - getMessageBodyWorkers()); - - clientResponse.bufferEntity(); - clientResponse.close(); - - return clientResponse; - - } catch (IOException e) { - e.printStackTrace(); - } catch (HttpException e) { - e.printStackTrace(); - } - return null; - } - - private HttpUriRequest getUriHttpRequest(final ClientRequest cr) { - final String strMethod = cr.getMethod(); - final URI uri = cr.getURI(); - - final HttpEntity entity = getHttpEntity(cr); - final HttpUriRequest request; - - if (strMethod.equals("GET")) { - request = new HttpGet(uri); - } else if (strMethod.equals("POST")) { - request = new HttpPost(uri); - } else if (strMethod.equals("PUT")) { - request = new HttpPut(uri); - } else if (strMethod.equals("DELETE")) { - request = new HttpDelete(uri); - } else if (strMethod.equals("HEAD")) { - request = new HttpHead(uri); - } else if (strMethod.equals("OPTIONS")) { - request = new HttpOptions(uri); - } else { - request = new HttpEntityEnclosingRequestBase() { - @Override - public String getMethod() { - return strMethod; - } - - @Override - public URI getURI() { - return uri; - } - }; - } - - if (entity != null && request instanceof HttpEntityEnclosingRequestBase) { - ((HttpEntityEnclosingRequestBase) request).setEntity(entity); - } else if (entity != null) { - throw new ClientHandlerException("Adding entity to http method " + cr.getMethod() + " is not supported."); - } - - return request; - } - - private HttpEntity getHttpEntity(final ClientRequest cr) { - final Object entity = cr.getEntity(); - - if (entity == null) - return null; - - final RequestEntityWriter requestEntityWriter = getRequestEntityWriter(cr); - - try { - HttpEntity httpEntity = new AbstractHttpEntity() { - @Override - public boolean isRepeatable() { - return false; - } - - @Override - public long getContentLength() { - return requestEntityWriter.getSize(); - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - return null; - } - - @Override - public void writeTo(OutputStream outputStream) throws IOException { - requestEntityWriter.writeRequestEntity(outputStream); - } - - @Override - public boolean isStreaming() { - return false; - } - }; - - if (cr.getProperties().get(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE) != null) { - // TODO return InputStreamEntity - return httpEntity; - } else { - return new BufferedHttpEntity(httpEntity); - } - } catch (Exception ex) { - // TODO warning/error? - } - - return null; - } - - private InBoundHeaders getInBoundHeaders(final HttpResponse response) { - final InBoundHeaders headers = new InBoundHeaders(); - final Header[] respHeaders = response.getAllHeaders(); - for (Header header : respHeaders) { - List list = headers.get(header.getName()); - if (list == null) { - list = new ArrayList(); - } - list.add(header.getValue()); - headers.put(header.getName(), list); - } - return headers; - } - - private static final class HttpClientResponseInputStream extends FilterInputStream { - - HttpClientResponseInputStream(final HttpResponse response) throws IOException { - super(getInputStream(response)); - } - - @Override - public void close() - throws IOException { - super.close(); - } - } - - private static InputStream getInputStream(final HttpResponse response) throws IOException { - - if (response.getEntity() == null) { - return new ByteArrayInputStream(new byte[0]); - } else { - final InputStream i = response.getEntity().getContent(); - if (i.markSupported()) - return i; - return new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE); - } - } -} diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java b/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java deleted file mode 100644 index 9c7f150c..00000000 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.kpelykh.docker.client; - -import org.apache.http.impl.io.AbstractSessionInputBuffer; -import org.apache.http.params.HttpParams; - -import java.io.IOException; -import java.io.InputStream; - -/** - * - */ -public class UnixSocketSessionInputBuffer extends AbstractSessionInputBuffer { - - @Override - protected void init(InputStream instream, int buffersize, HttpParams params) { - super.init(instream, buffersize, params); - } - - @Override - public boolean isDataAvailable(int timeout) throws IOException { - return true; - } -} diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java b/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java deleted file mode 100644 index 411096ff..00000000 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.kpelykh.docker.client; - -import org.apache.http.impl.io.AbstractSessionOutputBuffer; -import org.apache.http.params.HttpParams; - -import java.io.OutputStream; - -/** - * {@link org.apache.http.impl.io.AbstractSessionOutputBuffer} implementation for UNIX sockets. - */ -public class UnixSocketSessionOutputBuffer extends AbstractSessionOutputBuffer { - - @Override - protected void init(OutputStream outstream, int buffersize, HttpParams params) { - super.init(outstream, buffersize, params); - } -} diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index 3268ed56..af58c72a 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -330,7 +330,7 @@ public void testDiff() throws DockerException { int exitCode = dockerClient.waitContainer(container.getId()); assertThat(exitCode, equalTo(0)); - List filesystemDiff = dockerClient.containterDiff(container.getId()); + List filesystemDiff = dockerClient.containerDiff(container.getId()); LOG.info("Container DIFF: {}", filesystemDiff.toString()); assertThat(filesystemDiff.size(), equalTo(1)); @@ -524,6 +524,15 @@ public void commitImage() throws DockerException { assertThat(imageInspectResponse.getParent(), equalTo(busyboxImg.getId())); } + @Test + public void testPush() throws Exception { + + + + fail(); + + } + @Test public void testRemoveImage() throws DockerException, InterruptedException { From b69babb8a44e06a70915fc9c0e3389357374da6b Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sat, 12 Apr 2014 16:57:58 +0100 Subject: [PATCH 11/34] docker 0.9 compat --- .../docker/client/model/ContainerInspectResponse.java | 7 ++++++- .../java/com/kpelykh/docker/client/model/HostConfig.java | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java index 04d2f8c9..1a93a6c4 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -3,7 +3,6 @@ import org.codehaus.jackson.annotate.JsonProperty; -import java.util.Arrays; import java.util.Map; /** @@ -64,6 +63,12 @@ public class ContainerInspectResponse { @JsonProperty("HostConfig") private HostConfig hostConfig; + /** + * http://blog.docker.io/2014/03/docker-0-9-introducing-execution-drivers-and-libcontainer/ + */ + @JsonProperty("ExecDriver") + private String execDriver; + public String getId() { return id; } diff --git a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java index 47a12fe9..b0c26a3f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonProperty; import java.util.Arrays; @@ -45,7 +46,9 @@ public String[] getBinds() { public void setBinds(String[] binds) { this.binds = binds; } - + + // TODO - causes jackson conflict with tests + @JsonIgnore public void setBinds(final BoundHostVolumes volumes) { setBinds(volumes.asBinds()); } From 16507aef17821938d0e2a5776c031eb07cb5ef11 Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sat, 12 Apr 2014 18:01:41 +0100 Subject: [PATCH 12/34] docker 0.9 compat --- .../com/kpelykh/docker/client/model/HostConfig.java | 12 ++++++++++++ .../com/kpelykh/docker/client/model/Version.java | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java index b0c26a3f..e2b54c6d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -34,6 +34,9 @@ public class HostConfig { @JsonProperty("PublishAllPorts") private boolean publishAllPorts; + @JsonProperty("Dns") + private String dns; + public HostConfig() { this.binds = null; } @@ -101,6 +104,14 @@ public void setPublishAllPorts(boolean publishAllPorts) { this.publishAllPorts = publishAllPorts; } + public String getDns() { + return dns; + } + + public void setDns(String dns) { + this.dns = dns; + } + @Override public String toString() { return "HostConfig{" + @@ -111,6 +122,7 @@ public String toString() { ", portBindings=" + portBindings + ", privileged=" + privileged + ", publishAllPorts=" + publishAllPorts + + ", dns='" + dns + '\'' + '}'; } diff --git a/src/main/java/com/kpelykh/docker/client/model/Version.java b/src/main/java/com/kpelykh/docker/client/model/Version.java index 915ae67e..9b8eb79f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -28,6 +28,8 @@ public class Version { @JsonProperty("Os") private String operatingSystem; + @JsonProperty + private String apiVersion; public String getVersion() { return version; @@ -77,6 +79,14 @@ public void setOperatingSystem(String operatingSystem) { this.operatingSystem = operatingSystem; } + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + @Override public String toString() { return "Version{" + @@ -86,6 +96,7 @@ public String toString() { ", kernelVersion='" + kernelVersion + '\'' + ", arch='" + arch + '\'' + ", operatingSystem='" + operatingSystem + '\'' + + ", apiVersion='" + apiVersion + '\'' + '}'; } } From 5140ab16cc8289b25c3c2eada2ae7f79ccb0dc54 Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 15 Apr 2014 11:57:28 +0200 Subject: [PATCH 13/34] Update to 1.10 API. Add Copy File Method. Its returns a TAR Stream. --- .../kpelykh/docker/client/DockerClient.java | 83 +- .../model/ContainerInspectResponse.java | 11 + .../docker/client/model/HostConfig.java | 35 +- .../kpelykh/docker/client/model/Version.java | 10 + .../docker/client/test/DockerClientTest.java | 1368 +++++++++-------- src/test/resources/testReadFile/Dockerfile | 9 + src/test/resources/testReadFile/oldFile.txt | 1 + src/test/resources/testReadFile/testrun.sh | 4 + 8 files changed, 858 insertions(+), 663 deletions(-) create mode 100644 src/test/resources/testReadFile/Dockerfile create mode 100644 src/test/resources/testReadFile/oldFile.txt create mode 100755 src/test/resources/testReadFile/testrun.sh diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index ce6b8a68..73d182c0 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -1,18 +1,15 @@ package com.kpelykh.docker.client; -import com.google.common.base.Preconditions; -import com.kpelykh.docker.client.model.*; -import com.kpelykh.docker.client.utils.CompressArchiveUtil; -import com.kpelykh.docker.client.utils.JsonClientFilter; -import com.sun.jersey.api.client.*; -import com.sun.jersey.api.client.WebResource.Builder; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.LoggingFilter; -import com.sun.jersey.api.json.JSONConfiguration; -import com.sun.jersey.client.apache4.ApacheHttpClient4; -import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; -import com.sun.jersey.core.util.MultivaluedMapImpl; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.client.HttpClient; @@ -26,12 +23,34 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.UUID; +import com.google.common.base.Preconditions; +import com.kpelykh.docker.client.model.ChangeLog; +import com.kpelykh.docker.client.model.CommitConfig; +import com.kpelykh.docker.client.model.Container; +import com.kpelykh.docker.client.model.ContainerConfig; +import com.kpelykh.docker.client.model.ContainerCreateResponse; +import com.kpelykh.docker.client.model.ContainerInspectResponse; +import com.kpelykh.docker.client.model.HostConfig; +import com.kpelykh.docker.client.model.Image; +import com.kpelykh.docker.client.model.ImageInspectResponse; +import com.kpelykh.docker.client.model.Info; +import com.kpelykh.docker.client.model.SearchItem; +import com.kpelykh.docker.client.model.Version; +import com.kpelykh.docker.client.utils.CompressArchiveUtil; +import com.kpelykh.docker.client.utils.JsonClientFilter; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.GenericType; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.WebResource.Builder; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.api.json.JSONConfiguration; +import com.sun.jersey.client.apache4.ApacheHttpClient4; +import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; +import com.sun.jersey.core.util.MultivaluedMapImpl; /** * @@ -48,7 +67,7 @@ public class DockerClient private String restEndpointUrl; public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.8"; + restEndpointUrl = serverUrl + "/v1.10"; ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); @@ -696,4 +715,28 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio } + public InputStream copyFile(String containerId, String resource) throws DockerException { + + HashMap params = new HashMap(); + params.put("Resource", resource); + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/copy", containerId)); + + try { + LOGGER.trace("POST: {}", webResource); + return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).entity(params, MediaType.APPLICATION_JSON).post(InputStream.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 404) { + throw new DockerException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + + } + } diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java index 04d2f8c9..f86fc481 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -64,6 +64,9 @@ public class ContainerInspectResponse { @JsonProperty("HostConfig") private HostConfig hostConfig; + @JsonProperty("ExecDriver") + private String execDriver; + public String getId() { return id; } @@ -199,6 +202,14 @@ public HostConfig getHostConfig() { public void setHostConfig(HostConfig hostConfig) { this.hostConfig = hostConfig; } + + public void setExecDriver(String execDriver) { + this.execDriver = execDriver; + } + + public String getExecDriver() { + return execDriver; + } public class NetworkSettings { diff --git a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java index e124cf0d..c0cfe305 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -33,6 +33,15 @@ public class HostConfig { @JsonProperty("PublishAllPorts") private boolean publishAllPorts; + @JsonProperty("Dns") + private String dns; + + @JsonProperty("DnsSearch") + private String dnsSearch; + + @JsonProperty("VolumesFrom") + private String volumesFrom; + public HostConfig() { this.binds = null; } @@ -93,7 +102,31 @@ public boolean isPublishAllPorts() { public void setPublishAllPorts(boolean publishAllPorts) { this.publishAllPorts = publishAllPorts; } - + + public String getDns() { + return dns; + } + + public void setDns(String dns) { + this.dns = dns; + } + + public void setDnsSearch(String dnsSearch) { + this.dnsSearch = dnsSearch; + } + + public String getDnsSearch() { + return dnsSearch; + } + + public void setVolumesFrom(String volumesFrom) { + this.volumesFrom = volumesFrom; + } + + public String getVolumesFrom() { + return volumesFrom; + } + @Override public String toString() { return "HostConfig{" + diff --git a/src/main/java/com/kpelykh/docker/client/model/Version.java b/src/main/java/com/kpelykh/docker/client/model/Version.java index 915ae67e..017c49a3 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -28,6 +28,8 @@ public class Version { @JsonProperty("Os") private String operatingSystem; + @JsonProperty("ApiVersion") + private String apiVersion; public String getVersion() { return version; @@ -76,6 +78,14 @@ public String getOperatingSystem() { public void setOperatingSystem(String operatingSystem) { this.operatingSystem = operatingSystem; } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + public String getApiVersion() { + return apiVersion; + } @Override public String toString() { diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index 06656efa..6a83c937 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -3,8 +3,10 @@ import com.kpelykh.docker.client.DockerClient; import com.kpelykh.docker.client.DockerException; import com.kpelykh.docker.client.model.*; - import com.sun.jersey.api.client.ClientResponse; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.io.IOUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; @@ -14,7 +16,6 @@ import org.testng.Assert; import org.testng.ITestResult; import org.testng.annotations.*; - import java.io.*; import java.lang.reflect.Method; import java.net.DatagramSocket; @@ -22,756 +23,839 @@ import java.util.ArrayList; import java.util.List; + import static ch.lambdaj.Lambda.filter; import static ch.lambdaj.Lambda.selectUnique; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.hamcrest.Matchers.hasItem; import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField; /** * Unit test for DockerClient. + * * @author Konstantin Pelykh (kpelykh@gmail.com) */ -public class DockerClientTest extends Assert -{ - public static final Logger LOG = LoggerFactory.getLogger(DockerClientTest.class); - - private DockerClient dockerClient; - - private List tmpImgs = new ArrayList(); - private List tmpContainers = new ArrayList(); - - @BeforeTest - public void beforeTest() throws DockerException { - LOG.info("======================= BEFORETEST ======================="); - String url = System.getProperty("docker.url", "http://localhost:4243"); - LOG.info("Connecting to Docker server at " + url); - dockerClient = new DockerClient(url); - - LOG.info("Creating image 'busybox'"); - dockerClient.pull("busybox"); - - assertNotNull(dockerClient); - LOG.info("======================= END OF BEFORETEST =======================\n\n"); - } - - @AfterTest - public void afterTest() { - LOG.info("======================= END OF AFTERTEST ======================="); - } - - @BeforeMethod - public void beforeMethod(Method method) { - LOG.info(String.format("################################## STARTING %s ##################################", method.getName())); - } - - @AfterMethod - public void afterMethod(ITestResult result) { - - for (String container : tmpContainers) { - LOG.info("Cleaning up temporary container {}", container); - try { - dockerClient.stopContainer(container); - dockerClient.kill(container); - dockerClient.removeContainer(container); - } catch (DockerException ignore) {} - } - - for (String image : tmpImgs) { - LOG.info("Cleaning up temporary image {}", image); - try { - dockerClient.removeImage(image); - } catch (DockerException ignore) {} - } - - LOG.info("################################## END OF {} ##################################\n", result.getName()); - } - - /* - * ######################### - * ## INFORMATION TESTS ## - * ######################### - */ - - @Test - public void testDockerVersion() throws DockerException { - Version version = dockerClient.version(); - LOG.info(version.toString()); - - assertTrue(version.getGoVersion().length() > 0); - assertTrue(version.getVersion().length() > 0); - - assertEquals(StringUtils.split(version.getVersion(), ".").length, 3); - - } - - @Test - public void testDockerInfo() throws DockerException { - Info dockerInfo = dockerClient.info(); - LOG.info(dockerInfo.toString()); - - assertTrue(dockerInfo.toString().contains("containers")); - assertTrue(dockerInfo.toString().contains("images")); - assertTrue(dockerInfo.toString().contains("debug")); - - assertTrue(dockerInfo.getContainers() > 0); - assertTrue(dockerInfo.getImages() > 0); - assertTrue(dockerInfo.getNFd() > 0); - assertTrue(dockerInfo.getNGoroutines() > 0); - assertTrue(dockerInfo.isMemoryLimit()); - } - - @Test - public void testDockerSearch() throws DockerException { - List dockerSearch = dockerClient.search("busybox"); - LOG.info("Search returned {}", dockerSearch.toString()); - - Matcher matcher = hasItem(hasField("name", equalTo("busybox"))); - assertThat(dockerSearch, matcher); - - assertThat(filter(hasField("name", is("busybox")), dockerSearch).size(), equalTo(1)); - } - - /* - * ################### - * ## LISTING TESTS ## - * ################### - */ - - - @Test - public void testImages() throws DockerException { - List images = dockerClient.getImages(true); - assertThat(images, notNullValue()); - LOG.info("Images List: {}", images); - Info info = dockerClient.info(); - - assertThat(images.size(), equalTo(info.getImages())); - - Image img = images.get(0); - assertThat(img.getCreated(), is(greaterThan(0L)) ); - assertThat(img.getVirtualSize(), is(greaterThan(0L)) ); - assertThat(img.getId(), not(isEmptyString())); - assertThat(img.getTag(), not(isEmptyString())); - assertThat(img.getRepository(), not(isEmptyString())); - } - - - @Test - public void testListContainers() throws DockerException { - List containers = dockerClient.listContainers(true); - assertThat(containers, notNullValue()); - LOG.info("Container List: {}", containers); - - int size = containers.size(); - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[]{"echo"}); - - ContainerCreateResponse container1 = dockerClient.createContainer(containerConfig); - assertThat(container1.getId(), not(isEmptyString())); - dockerClient.startContainer(container1.getId()); - tmpContainers.add(container1.getId()); - - List containers2 = dockerClient.listContainers(true); - assertThat(size + 1, is(equalTo(containers2.size()))); - Matcher matcher = hasItem(hasField("id", startsWith(container1.getId()))); - assertThat(containers2, matcher); - - List filteredContainers = filter(hasField("id", startsWith(container1.getId())), containers2); - assertThat(filteredContainers.size(), is(equalTo(1))); - - Container container2 = filteredContainers.get(0); - assertThat(container2.getCommand(), not(isEmptyString())); - assertThat(container2.getImage(), equalTo("busybox:latest")); - } - - - /* - * ##################### - * ## CONTAINER TESTS ## - * ##################### - */ - - @Test - public void testCreateContainer() throws DockerException { - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[]{"true"}); - - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - - LOG.info("Created container {}", container.toString()); - - assertThat(container.getId(), not(isEmptyString())); - - tmpContainers.add(container.getId()); - } - - @Test - public void testStartContainer() throws DockerException { - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[]{"true"}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - boolean add = tmpContainers.add(container.getId()); - - dockerClient.startContainer(container.getId()); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - - assertThat(containerInspectResponse.config, is(notNullValue())); - assertThat(containerInspectResponse.getId(), not(isEmptyString())); - - assertThat(containerInspectResponse.getId(), startsWith(container.getId())); - - assertThat(containerInspectResponse.getImage(), not(isEmptyString())); - assertThat(containerInspectResponse.getState(), is(notNullValue())); +public class DockerClientTest extends Assert { + public static final Logger LOG = LoggerFactory + .getLogger(DockerClientTest.class); + + private DockerClient dockerClient; + + private List tmpImgs = new ArrayList(); + private List tmpContainers = new ArrayList(); + + @BeforeTest + public void beforeTest() throws DockerException { + LOG.info("======================= BEFORETEST ======================="); + String url = System.getProperty("docker.url", "http://localhost:4243"); + LOG.info("Connecting to Docker server at " + url); + dockerClient = new DockerClient(url); + + LOG.info("Creating image 'busybox'"); + dockerClient.pull("busybox"); + + assertNotNull(dockerClient); + LOG.info("======================= END OF BEFORETEST =======================\n\n"); + } + + @AfterTest + public void afterTest() { + LOG.info("======================= END OF AFTERTEST ======================="); + } + + @BeforeMethod + public void beforeMethod(Method method) { + LOG.info(String + .format("################################## STARTING %s ##################################", + method.getName())); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + + for (String container : tmpContainers) { + LOG.info("Cleaning up temporary container {}", container); + try { + dockerClient.stopContainer(container); + dockerClient.kill(container); + dockerClient.removeContainer(container); + } catch (DockerException ignore) { + } + } + + for (String image : tmpImgs) { + LOG.info("Cleaning up temporary image {}", image); + try { + dockerClient.removeImage(image); + } catch (DockerException ignore) { + } + } + + LOG.info( + "################################## END OF {} ##################################\n", + result.getName()); + } + + /* + * ######################### ## INFORMATION TESTS ## + * ######################### + */ + + @Test + public void testDockerVersion() throws DockerException { + Version version = dockerClient.version(); + LOG.info(version.toString()); + + assertTrue(version.getGoVersion().length() > 0); + assertTrue(version.getVersion().length() > 0); + + assertEquals(StringUtils.split(version.getVersion(), ".").length, 3); + + } + + @Test + public void testDockerInfo() throws DockerException { + Info dockerInfo = dockerClient.info(); + LOG.info(dockerInfo.toString()); + + assertTrue(dockerInfo.toString().contains("containers")); + assertTrue(dockerInfo.toString().contains("images")); + assertTrue(dockerInfo.toString().contains("debug")); + + assertTrue(dockerInfo.getContainers() > 0); + assertTrue(dockerInfo.getImages() > 0); + assertTrue(dockerInfo.getNFd() > 0); + assertTrue(dockerInfo.getNGoroutines() > 0); + assertTrue(dockerInfo.isMemoryLimit()); + } + + @Test + public void testDockerSearch() throws DockerException { + List dockerSearch = dockerClient.search("busybox"); + LOG.info("Search returned {}", dockerSearch.toString()); + + Matcher matcher = hasItem(hasField("name", equalTo("busybox"))); + assertThat(dockerSearch, matcher); + + assertThat( + filter(hasField("name", is("busybox")), dockerSearch).size(), + equalTo(1)); + } + + /* + * ################### ## LISTING TESTS ## ################### + */ + + @Test + public void testImages() throws DockerException { + List images = dockerClient.getImages(true); + assertThat(images, notNullValue()); + LOG.info("Images List: {}", images); + Info info = dockerClient.info(); + + assertThat(images.size(), equalTo(info.getImages())); + + Image img = images.get(0); + assertThat(img.getCreated(), is(greaterThan(0L))); + assertThat(img.getVirtualSize(), is(greaterThan(0L))); + assertThat(img.getId(), not(isEmptyString())); + assertThat(img.getTag(), not(isEmptyString())); + assertThat(img.getRepository(), not(isEmptyString())); + } + + @Test + public void testListContainers() throws DockerException { + List containers = dockerClient.listContainers(true); + assertThat(containers, notNullValue()); + LOG.info("Container List: {}", containers); + + int size = containers.size(); + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "echo" }); + + ContainerCreateResponse container1 = dockerClient + .createContainer(containerConfig); + assertThat(container1.getId(), not(isEmptyString())); + dockerClient.startContainer(container1.getId()); + tmpContainers.add(container1.getId()); - assertThat(containerInspectResponse.getState().running, is(true)); + List containers2 = dockerClient.listContainers(true); + assertThat(size + 1, is(equalTo(containers2.size()))); + Matcher matcher = hasItem(hasField("id", startsWith(container1.getId()))); + assertThat(containers2, matcher); - if (!containerInspectResponse.getState().running) { - assertThat(containerInspectResponse.getState().exitCode, is(equalTo(0))); - } + List filteredContainers = filter( + hasField("id", startsWith(container1.getId())), containers2); + assertThat(filteredContainers.size(), is(equalTo(1))); - } + Container container2 = filteredContainers.get(0); + assertThat(container2.getCommand(), not(isEmptyString())); + assertThat(container2.getImage(), equalTo("busybox:latest")); + } - @Test - public void testWaitContainer() throws DockerException { + /* + * ##################### ## CONTAINER TESTS ## ##################### + */ - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[]{"true"}); + @Test + public void testCreateContainer() throws DockerException { + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "true" }); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - tmpContainers.add(container.getId()); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); - dockerClient.startContainer(container.getId()); + LOG.info("Created container {}", container.toString()); - int exitCode = dockerClient.waitContainer(container.getId()); - LOG.info("Container exit code: {}", exitCode); + assertThat(container.getId(), not(isEmptyString())); - assertThat(exitCode, equalTo(0)); + tmpContainers.add(container.getId()); + } - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: {}", containerInspectResponse.toString()); + @Test + public void testStartContainer() throws DockerException { - assertThat(containerInspectResponse.getState().running, is(equalTo(false))); - assertThat(containerInspectResponse.getState().exitCode, is(equalTo(exitCode))); + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "true" }); - } + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + boolean add = tmpContainers.add(container.getId()); - @Test - public void testLogs() throws DockerException, IOException { + dockerClient.startContainer(container.getId()); - String snippet = "hello world"; + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"/bin/echo", snippet}); + assertThat(containerInspectResponse.config, is(notNullValue())); + assertThat(containerInspectResponse.getId(), not(isEmptyString())); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); + assertThat(containerInspectResponse.getId(), + startsWith(container.getId())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + assertThat(containerInspectResponse.getImage(), not(isEmptyString())); + assertThat(containerInspectResponse.getState(), is(notNullValue())); - int exitCode = dockerClient.waitContainer(container.getId()); + assertThat(containerInspectResponse.getState().running, is(true)); - assertThat(exitCode, equalTo(0)); + if (!containerInspectResponse.getState().running) { + assertThat(containerInspectResponse.getState().exitCode, + is(equalTo(0))); + } - ClientResponse response = dockerClient.logContainer(container.getId()); + } - StringWriter logwriter = new StringWriter(); + @Test + public void testWaitContainer() throws DockerException { - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + (itr.hasNext() ? "\n" : "")); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "true" }); - String fullLog = logwriter.toString(); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + tmpContainers.add(container.getId()); - LOG.info("Container log: {}", fullLog); - assertThat(fullLog, endsWith(snippet)); - } + dockerClient.startContainer(container.getId()); - @Test - public void testDiff() throws DockerException { - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"touch", "/test"}); + int exitCode = dockerClient.waitContainer(container.getId()); + LOG.info("Container exit code: {}", exitCode); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - boolean add = tmpContainers.add(container.getId()); - int exitCode = dockerClient.waitContainer(container.getId()); - assertThat(exitCode, equalTo(0)); + assertThat(exitCode, equalTo(0)); - List filesystemDiff = dockerClient.containterDiff(container.getId()); - LOG.info("Container DIFF: {}", filesystemDiff.toString()); + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - assertThat(filesystemDiff.size(), equalTo(3)); - ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); + assertThat(containerInspectResponse.getState().running, + is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, + is(equalTo(exitCode))); - assertThat(testChangeLog, hasField("path", equalTo("/test"))); - assertThat(testChangeLog, hasField("kind", equalTo(1))); - } + } - @Test - public void testStopContainer() throws DockerException { + @Test + public void testLogs() throws DockerException, IOException { - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); + String snippet = "hello world"; - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "/bin/echo", snippet }); - LOG.info("Stopping container: {}", container.getId()); - dockerClient.stopContainer(container.getId(), 2); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: {}", containerInspectResponse.toString()); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); - assertThat(containerInspectResponse.getState().running, is(equalTo(false))); - assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); - } + int exitCode = dockerClient.waitContainer(container.getId()); - @Test - public void testKillContainer() throws DockerException { + assertThat(exitCode, equalTo(0)); - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); + ClientResponse response = dockerClient.logContainer(container.getId()); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + StringWriter logwriter = new StringWriter(); - LOG.info("Killing container: {}", container.getId()); - dockerClient.kill(container.getId()); + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter.write(line + (itr.hasNext() ? "\n" : "")); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(response.getEntityInputStream()); + } - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: {}", containerInspectResponse.toString()); + String fullLog = logwriter.toString(); - assertThat(containerInspectResponse.getState().running, is(equalTo(false))); - assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); + LOG.info("Container log: {}", fullLog); + assertThat(fullLog, endsWith(snippet)); + } - } + @Test + public void testCopyFile() throws DockerException, IOException { - @Test - public void restartContainer() throws DockerException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("testReadFile").getFile()); + String containerId = dockerfileBuild(baseDir, "hello.txt Created"); - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); + String fileName = "hello.txt"; + String fileText = "Hello Word"; - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + InputStream response = dockerClient.copyFile(containerId, fileName); + TarArchiveInputStream files = new TarArchiveInputStream(response); + + TarArchiveEntry entry = files.getNextTarEntry(); + + byte[] content = new byte[(int) entry.getSize()]; + files.read(content, 0, content.length); + - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: {}", containerInspectResponse.toString()); + String fullLog = new String(content); - String startTime = containerInspectResponse.getState().startedAt; + LOG.info("Read File: {}", fullLog); + assertThat(fullLog.trim(), endsWith(fileText)); + } - dockerClient.restart(container.getId(), 2); + @Test + public void testDiff() throws DockerException { + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "touch", "/test" }); - ContainerInspectResponse containerInspectResponse2 = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect After Restart: {}", containerInspectResponse2.toString()); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + boolean add = tmpContainers.add(container.getId()); + int exitCode = dockerClient.waitContainer(container.getId()); + assertThat(exitCode, equalTo(0)); - String startTime2 = containerInspectResponse2.getState().startedAt; + List filesystemDiff = dockerClient.containterDiff(container.getId()); + LOG.info("Container DIFF: {}", filesystemDiff.toString()); - assertThat(startTime, not(equalTo(startTime2))); + assertThat(filesystemDiff.size(), equalTo(4)); + ChangeLog testChangeLog = selectUnique(filesystemDiff, + hasField("path", equalTo("/test"))); - assertThat(containerInspectResponse.getState().running, is(equalTo(true))); + assertThat(testChangeLog, hasField("path", equalTo("/test"))); + assertThat(testChangeLog, hasField("kind", equalTo(1))); + } - dockerClient.kill(container.getId()); - } + @Test + public void testStopContainer() throws DockerException { - @Test - public void removeContainer() throws DockerException { + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "sleep", "9999" }); - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"true"}); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); + LOG.info("Stopping container: {}", container.getId()); + dockerClient.stopContainer(container.getId(), 2); - dockerClient.startContainer(container.getId()); - dockerClient.waitContainer(container.getId()); - tmpContainers.add(container.getId()); + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - LOG.info("Removing container: {}", container.getId()); - dockerClient.removeContainer(container.getId()); + assertThat(containerInspectResponse.getState().running, + is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, + not(equalTo(0))); + } - List containers2 = dockerClient.listContainers(true); - Matcher matcher = not(hasItem(hasField("id", startsWith(container.getId())))); - assertThat(containers2, matcher); + @Test + public void testKillContainer() throws DockerException { - } + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "sleep", "9999" }); - /* - * ################## - * ## IMAGES TESTS ## - * ################## - * */ + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); - @Test - public void testPullImage() throws DockerException, IOException { + LOG.info("Killing container: {}", container.getId()); + dockerClient.kill(container.getId()); - String testImage = "kpelykh/vimbase"; + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - LOG.info("Removing image: {}", testImage); - dockerClient.removeImage(testImage); + assertThat(containerInspectResponse.getState().running, + is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, + not(equalTo(0))); - Info info = dockerClient.info(); - LOG.info("Client info: {}", info.toString()); + } - int imgCount= info.getImages(); + @Test + public void restartContainer() throws DockerException { - LOG.info("Pulling image: {}", testImage); + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "sleep", "9999" }); - ClientResponse response = dockerClient.pull(testImage); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); - StringWriter logwriter = new StringWriter(); + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + "\n"); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } + String startTime = containerInspectResponse.getState().startedAt; - String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Pulling repository kpelykh/vimbase")); + dockerClient.restart(container.getId(), 2); - tmpImgs.add(testImage); + ContainerInspectResponse containerInspectResponse2 = dockerClient + .inspectContainer(container.getId()); + LOG.info("Container Inspect After Restart: {}", + containerInspectResponse2.toString()); - info = dockerClient.info(); - LOG.info("Client info after pull, {}", info.toString()); + String startTime2 = containerInspectResponse2.getState().startedAt; - assertThat(imgCount + 1, equalTo(info.getImages())); + assertThat(startTime, not(equalTo(startTime2))); - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(testImage); - LOG.info("Image Inspect: {}", imageInspectResponse.toString()); - assertThat(imageInspectResponse, notNullValue()); - } + assertThat(containerInspectResponse.getState().running, + is(equalTo(true))); + dockerClient.kill(container.getId()); + } - @Test - public void commitImage() throws DockerException { + @Test + public void removeContainer() throws DockerException { - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"touch", "/test"}); + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "true" }); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); - LOG.info("Commiting container: {}", container.toString()); - String imageId = dockerClient.commit(new CommitConfig(container.getId())); - tmpImgs.add(imageId); + dockerClient.startContainer(container.getId()); + dockerClient.waitContainer(container.getId()); + tmpContainers.add(container.getId()); - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - LOG.info("Image Inspect: {}", imageInspectResponse.toString()); + LOG.info("Removing container: {}", container.getId()); + dockerClient.removeContainer(container.getId()); - assertThat(imageInspectResponse, hasField("container", startsWith(container.getId()))); - assertThat(imageInspectResponse.getContainerConfig().getImage(), equalTo("busybox")); + List containers2 = dockerClient.listContainers(true); + Matcher matcher = not(hasItem(hasField("id", + startsWith(container.getId())))); + assertThat(containers2, matcher); - ImageInspectResponse busyboxImg = dockerClient.inspectImage("busybox"); + } - assertThat(imageInspectResponse.getParent(), equalTo(busyboxImg.getId())); - } + /* + * ################## ## IMAGES TESTS ## ################## + */ - @Test - public void testRemoveImage() throws DockerException, InterruptedException { + @Test + public void testPullImage() throws DockerException, IOException { + String testImage = "kpelykh/vimbase"; - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"touch", "/test"}); + LOG.info("Removing image: {}", testImage); + dockerClient.removeImage(testImage); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); + Info info = dockerClient.info(); + LOG.info("Client info: {}", info.toString()); - LOG.info("Commiting container {}", container.toString()); - String imageId = dockerClient.commit(new CommitConfig(container.getId())); - tmpImgs.add(imageId); + int imgCount = info.getImages(); - dockerClient.stopContainer(container.getId()); - dockerClient.kill(container.getId()); - dockerClient.removeContainer(container.getId()); + LOG.info("Pulling image: {}", testImage); - tmpContainers.remove(container.getId()); - LOG.info("Removing image: {}", imageId); - dockerClient.removeImage(imageId); + ClientResponse response = dockerClient.pull(testImage); - List containers = dockerClient.listContainers(true); - Matcher matcher = not(hasItem(hasField("id", startsWith(imageId)))); - assertThat(containers, matcher); - } + StringWriter logwriter = new StringWriter(); + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter.write(line + "\n"); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(response.getEntityInputStream()); + } - /* - * - * ################ - * ## MISC TESTS ## - * ################ - */ + String fullLog = logwriter.toString(); + assertThat(fullLog, + containsString("Pulling repository kpelykh/vimbase")); - @Test - public void testRunShlex() throws DockerException { + tmpImgs.add(testImage); - String[] commands = new String[] { - "true", - "echo \"The Young Descendant of Tepes & Septette for the Dead Princess\"", - "echo -n 'The Young Descendant of Tepes & Septette for the Dead Princess'", - "/bin/sh -c echo Hello World", - "/bin/sh -c echo 'Hello World'", - "echo 'Night of Nights'", - "true && echo 'Night of Nights'" - }; + info = dockerClient.info(); + LOG.info("Client info after pull, {}", info.toString()); - for (String command : commands) { - LOG.info("Running command: [{}]", command); + assertThat(imgCount + 1, equalTo(info.getImages())); - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd( commands ); + ImageInspectResponse imageInspectResponse = dockerClient + .inspectImage(testImage); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); + assertThat(imageInspectResponse, notNullValue()); + } - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); - int exitcode = dockerClient.waitContainer(container.getId()); - assertThat(exitcode, equalTo(0)); - } - } + @Test + public void commitImage() throws DockerException { + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "touch", "/test" }); - @Test - public void testNginxDockerfileBuilder() throws DockerException, IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); - ClientResponse response = dockerClient.build(baseDir); - - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + "\n"); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Successfully built")); - - String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect: {}", imageInspectResponse.toString()); - tmpImgs.add(imageInspectResponse.getId()); - - assertThat(imageInspectResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); - } - - @Test - public void testDockerBuilderAddFile() throws DockerException, IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile()); - dockerfileBuild(baseDir, "Successfully executed testrun.sh"); - } - - @Test - public void testDockerBuilderAddFolder() throws DockerException, IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile()); - dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh"); - } - - @Test - public void testNetCatDockerfileBuilder() throws DockerException, IOException, InterruptedException { - File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); - - ClientResponse response = dockerClient.build(baseDir); - - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + "\n"); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Successfully built")); - - String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect: {}", imageInspectResponse.toString()); - tmpImgs.add(imageInspectResponse.getId()); - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage(imageInspectResponse.getId()); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - assertThat(container.getId(), not(isEmptyString())); - dockerClient.startContainer(container.getId()); - tmpContainers.add(container.getId()); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - - assertThat(containerInspectResponse.getId(), notNullValue()); - assertThat(containerInspectResponse.getNetworkSettings().ports, notNullValue()); - - //No use as such if not running on the server - for(String portstr : containerInspectResponse.getNetworkSettings().ports.getAllPorts().keySet()){ - - Ports.Port p = containerInspectResponse.getNetworkSettings().ports.getAllPorts().get(portstr); - int port = Integer.valueOf(p.getHostPort()); - LOG.info("Checking port {} is open", port); - assertThat(available(port), is(false)); - } - dockerClient.stopContainer(container.getId(), 0); - - } - - - // UTIL - - /** - * Checks to see if a specific port is available. - * - * @param port the port to check for availability - */ - public static boolean available(int port) { - if (port < 1100 || port > 60000) { - throw new IllegalArgumentException("Invalid start port: " + port); - } - - ServerSocket ss = null; - DatagramSocket ds = null; - try { - ss = new ServerSocket(port); - ss.setReuseAddress(true); - ds = new DatagramSocket(port); - ds.setReuseAddress(true); - return true; - } catch (IOException e) { - } finally { - if (ds != null) { - ds.close(); - } - - if (ss != null) { - try { - ss.close(); - } catch (IOException e) { - /* should not be thrown */ - } - } - } - - return false; - } - - private void dockerfileBuild(File baseDir, String expectedText) throws DockerException, IOException { - - //Build image - ClientResponse response = dockerClient.build(baseDir); - - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + "\n"); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Successfully built")); - - String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); - - //Create container based on image - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage(imageId); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container: {}", container.toString()); - assertThat(container.getId(), not(isEmptyString())); - - dockerClient.startContainer(container.getId()); - dockerClient.waitContainer(container.getId()); - - tmpContainers.add(container.getId()); - - //Log container - ClientResponse logResponse = dockerClient.logContainer(container.getId()); - - StringWriter logwriter2 = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator(logResponse.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter2.write(line + (itr.hasNext() ? "\n" : "")); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(logResponse.getEntityInputStream()); - } - - assertThat(logwriter2.toString(), endsWith(expectedText)); - } + LOG.info("Commiting container: {}", container.toString()); + String imageId = dockerClient + .commit(new CommitConfig(container.getId())); + tmpImgs.add(imageId); + + ImageInspectResponse imageInspectResponse = dockerClient + .inspectImage(imageId); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); + + assertThat(imageInspectResponse, + hasField("container", startsWith(container.getId()))); + assertThat(imageInspectResponse.getContainerConfig().getImage(), + equalTo("busybox")); + + ImageInspectResponse busyboxImg = dockerClient.inspectImage("busybox"); + + assertThat(imageInspectResponse.getParent(), + equalTo(busyboxImg.getId())); + } + + @Test + public void testRemoveImage() throws DockerException, InterruptedException { + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "touch", "/test" }); + + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); + + LOG.info("Commiting container {}", container.toString()); + String imageId = dockerClient + .commit(new CommitConfig(container.getId())); + tmpImgs.add(imageId); + + dockerClient.stopContainer(container.getId()); + dockerClient.kill(container.getId()); + dockerClient.removeContainer(container.getId()); + + tmpContainers.remove(container.getId()); + LOG.info("Removing image: {}", imageId); + dockerClient.removeImage(imageId); + + List containers = dockerClient.listContainers(true); + Matcher matcher = not(hasItem(hasField("id", startsWith(imageId)))); + assertThat(containers, matcher); + } + + /* + * + * ################ ## MISC TESTS ## ################ + */ + + @Test + public void testRunShlex() throws DockerException { + + String[] commands = new String[] { + "true", + "echo \"The Young Descendant of Tepes & Septette for the Dead Princess\"", + "echo -n 'The Young Descendant of Tepes & Septette for the Dead Princess'", + "/bin/sh -c echo Hello World", "/bin/sh -c echo 'Hello World'", + "echo 'Night of Nights'", "true && echo 'Night of Nights'" }; + + for (String command : commands) { + LOG.info("Running command: [{}]", command); + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(commands); + + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); + int exitcode = dockerClient.waitContainer(container.getId()); + assertThat(exitcode, equalTo(0)); + } + } + + @Test + public void testNginxDockerfileBuilder() throws DockerException, + IOException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("nginx").getFile()); + + ClientResponse response = dockerClient.build(baseDir); + + StringWriter logwriter = new StringWriter(); + + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter.write(line + "\n"); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(response.getEntityInputStream()); + } + + String fullLog = logwriter.toString(); + assertThat(fullLog, containsString("Successfully built")); + + String imageId = StringUtils.substringBetween(fullLog, + "Successfully built ", "\\n\"}").trim(); + + ImageInspectResponse imageInspectResponse = dockerClient + .inspectImage(imageId); + assertThat(imageInspectResponse, not(nullValue())); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); + tmpImgs.add(imageInspectResponse.getId()); + + assertThat(imageInspectResponse.getAuthor(), + equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); + } + + @Test + public void testDockerBuilderAddFile() throws DockerException, IOException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("testAddFile").getFile()); + dockerfileBuild(baseDir, "Successfully executed testrun.sh"); + } + + @Test + public void testDockerBuilderAddFolder() throws DockerException, + IOException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("testAddFolder").getFile()); + dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh"); + } + + @Test + public void testNetCatDockerfileBuilder() throws DockerException, + IOException, InterruptedException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("netcat").getFile()); + + ClientResponse response = dockerClient.build(baseDir); + + StringWriter logwriter = new StringWriter(); + + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter.write(line + "\n"); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(response.getEntityInputStream()); + } + + String fullLog = logwriter.toString(); + assertThat(fullLog, containsString("Successfully built")); + + String imageId = StringUtils.substringBetween(fullLog, + "Successfully built ", "\\n\"}").trim(); + + ImageInspectResponse imageInspectResponse = dockerClient + .inspectImage(imageId); + assertThat(imageInspectResponse, not(nullValue())); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); + tmpImgs.add(imageInspectResponse.getId()); + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage(imageInspectResponse.getId()); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); + + ContainerInspectResponse containerInspectResponse = dockerClient + .inspectContainer(container.getId()); + + assertThat(containerInspectResponse.getId(), notNullValue()); + assertThat(containerInspectResponse.getNetworkSettings().ports, + notNullValue()); + + // No use as such if not running on the server + for (String portstr : containerInspectResponse.getNetworkSettings().ports + .getAllPorts().keySet()) { + + Ports.Port p = containerInspectResponse.getNetworkSettings().ports + .getAllPorts().get(portstr); + int port = Integer.valueOf(p.getHostPort()); + LOG.info("Checking port {} is open", port); + assertThat(available(port), is(false)); + } + dockerClient.stopContainer(container.getId(), 0); + + } + + // UTIL + + /** + * Checks to see if a specific port is available. + * + * @param port + * the port to check for availability + */ + public static boolean available(int port) { + if (port < 1100 || port > 60000) { + throw new IllegalArgumentException("Invalid start port: " + port); + } + + ServerSocket ss = null; + DatagramSocket ds = null; + try { + ss = new ServerSocket(port); + ss.setReuseAddress(true); + ds = new DatagramSocket(port); + ds.setReuseAddress(true); + return true; + } catch (IOException e) { + } finally { + if (ds != null) { + ds.close(); + } + + if (ss != null) { + try { + ss.close(); + } catch (IOException e) { + /* should not be thrown */ + } + } + } + + return false; + } + + private String dockerfileBuild(File baseDir, String expectedText) + throws DockerException, IOException { + + // Build image + ClientResponse response = dockerClient.build(baseDir); + + StringWriter logwriter = new StringWriter(); + + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter.write(line + "\n"); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(response.getEntityInputStream()); + } + + String fullLog = logwriter.toString(); + assertThat(fullLog, containsString("Successfully built")); + + String imageId = StringUtils.substringBetween(fullLog, + "Successfully built ", "\\n\"}").trim(); + + // Create container based on image + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage(imageId); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + LOG.info("Created container: {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainer(container.getId()); + dockerClient.waitContainer(container.getId()); + + tmpContainers.add(container.getId()); + + // Log container + ClientResponse logResponse = dockerClient.logContainer(container + .getId()); + + StringWriter logwriter2 = new StringWriter(); + + try { + LineIterator itr = IOUtils.lineIterator( + logResponse.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + logwriter2.write(line + (itr.hasNext() ? "\n" : "")); + LOG.info(line); + } + } finally { + IOUtils.closeQuietly(logResponse.getEntityInputStream()); + } + + assertThat(logwriter2.toString(), endsWith(expectedText)); + + return container.getId(); + } } \ No newline at end of file diff --git a/src/test/resources/testReadFile/Dockerfile b/src/test/resources/testReadFile/Dockerfile new file mode 100644 index 00000000..3dfe89f9 --- /dev/null +++ b/src/test/resources/testReadFile/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu + +# Copy testrun.sh files into the container + +ADD ./testrun.sh /tmp/ +ADD ./oldFile.txt / +RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh + +CMD ["testrun.sh"] diff --git a/src/test/resources/testReadFile/oldFile.txt b/src/test/resources/testReadFile/oldFile.txt new file mode 100644 index 00000000..ac1acee1 --- /dev/null +++ b/src/test/resources/testReadFile/oldFile.txt @@ -0,0 +1 @@ +Old File \ No newline at end of file diff --git a/src/test/resources/testReadFile/testrun.sh b/src/test/resources/testReadFile/testrun.sh new file mode 100755 index 00000000..d8b9508d --- /dev/null +++ b/src/test/resources/testReadFile/testrun.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "Hello Word" > hello.txt +echo "hello.txt Created" From bced4af29f59989fc6c9942bea5b056e72be5b55 Mon Sep 17 00:00:00 2001 From: luismclglass Date: Tue, 15 Apr 2014 12:05:33 +0200 Subject: [PATCH 14/34] Update README version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 406f3ca1..8e717511 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") -Supports a subset of the Docker Client API v1.8, Docker Server version 0.7.6 +Supports a subset of the Docker Client API v1.10, Docker Server version 0.10 ## Build with Maven From 321c67be9eb50d96b0acc6dcf94410b72413eca1 Mon Sep 17 00:00:00 2001 From: djsly Date: Tue, 15 Apr 2014 17:24:27 -0400 Subject: [PATCH 15/34] fixed typo --- src/main/java/com/kpelykh/docker/client/DockerClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index d0908d8d..609c84f2 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -548,7 +548,7 @@ public ClientResponse copyFile(String containerId, String resource) throws Docke } } - public List containterDiff(String containerId) throws DockerException, NotFoundException { + public List containerDiff(String containerId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); From ade01d1f28916dfd3d905cf71a98bfef7de332af Mon Sep 17 00:00:00 2001 From: djsly Date: Tue, 15 Apr 2014 18:45:54 -0400 Subject: [PATCH 16/34] adding right string format for ApiVersion --- src/main/java/com/kpelykh/docker/client/model/Version.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kpelykh/docker/client/model/Version.java b/src/main/java/com/kpelykh/docker/client/model/Version.java index 9b8eb79f..27ace86b 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -28,7 +28,7 @@ public class Version { @JsonProperty("Os") private String operatingSystem; - @JsonProperty + @JsonProperty("ApiVersion") private String apiVersion; public String getVersion() { From 216b756f95949c41761b9287e06d69bc9e981cc1 Mon Sep 17 00:00:00 2001 From: djsly Date: Tue, 22 Apr 2014 16:56:19 -0400 Subject: [PATCH 17/34] Copying a directory keeping the original directory --- src/main/java/com/kpelykh/docker/client/DockerClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 609c84f2..e33f6f44 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -724,7 +724,7 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro throw new DockerException(String.format("Source file %s doesnt' exist", src)); } if (src.isDirectory()) { - FileUtils.copyDirectory(src, tmpDockerContextFolder); + FileUtils.copyDirectoryToDirectory(src, tmpDockerContextFolder); } else { FileUtils.copyFileToDirectory(src, tmpDockerContextFolder); } From 0bcade70cb81d0e95c603e359a98afe3621944a6 Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Sat, 26 Apr 2014 22:52:18 +0100 Subject: [PATCH 18/34] moved to my own repo --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4938aa64..4b4b2215 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 7 - com.kpelykh + com.alexecollins docker-java jar 0.8.2-SNAPSHOT From 7cbba4b3d8afa9a9e39d0a93cd744bde88a7fa83 Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Sun, 27 Apr 2014 01:58:08 +0100 Subject: [PATCH 19/34] added push support --- .../kpelykh/docker/client/DockerClient.java | 1558 +++++++++-------- .../docker/client/model/AuthConfig.java | 56 + .../client/test/DockerClientAuthTest.java | 38 + .../docker/client/test/DockerPushTest.java | 45 +- 4 files changed, 969 insertions(+), 728 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/model/AuthConfig.java create mode 100644 src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index af0bedb3..108610e6 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -8,18 +8,24 @@ import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.LoggingFilter; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; import com.sun.jersey.core.util.MultivaluedMapImpl; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; import org.apache.http.client.HttpClient; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; +import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; @@ -30,736 +36,838 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.StringWriter; import java.util.List; import java.util.UUID; +import static org.apache.commons.io.IOUtils.closeQuietly; + /** - * * @author Konstantin Pelykh (kpelykh@gmail.com) - * */ -public class DockerClient -{ - - private static final Logger LOGGER = LoggerFactory.getLogger(DockerClient.class); - - private static DockerClient instance; - private Client client; - private String restEndpointUrl; - - public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.10"; - ClientConfig clientConfig = new DefaultClientConfig(); - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", 4243, PlainSocketFactory.getSocketFactory())); - - PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); - // Increase max total connection - cm.setMaxTotal(1000); - // Increase default max connection per route - cm.setDefaultMaxPerRoute(1000); - - HttpClient httpClient = new DefaultHttpClient(cm); - client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); - - //Experimental support for unix sockets: - //client = new UnixSocketClient(clientConfig); - - client.addFilter(new JsonClientFilter()); - } - - /** - ** MISC API - ** - **/ - - public Info info() throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + "/info"); - - try { - LOGGER.trace("GET: {}", webResource); - return webResource.accept(MediaType.APPLICATION_JSON).get(Info.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - } - - - public Version version() throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + "/version"); - - try { - LOGGER.trace("GET: {}", webResource); - return webResource.accept(MediaType.APPLICATION_JSON).get(Version.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - } - - - /** - ** IMAGE API - ** - **/ - - public ClientResponse pull(String repository) throws DockerException { - return this.pull(repository, null, null); - } - - public ClientResponse pull(String repository, String tag) throws DockerException { - return this.pull(repository, tag, null); - } - - public ClientResponse pull(String repository, String tag, String registry) throws DockerException { - Preconditions.checkNotNull(repository, "Repository was not specified"); - - if (StringUtils.countMatches(repository, ":") == 1) { - String repositoryTag[] = StringUtils.split(repository); - repository = repositoryTag[0]; - tag = repositoryTag[1]; - - } - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("tag", tag); - params.add("fromImage", repository); - params.add("registry", registry); - - WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params); - - try { - LOGGER.trace("POST: {}", webResource); - return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - } - - /** - * Create an image by importing the given stream of a tar file. - * - * @param repository the repository to import to - * @param tag any tag for this image - * @param imageStream the InputStream of the tar file - * @return an {@link ImageCreateResponse} containing the id of the imported image - * @throws DockerException if the import fails for some reason. - */ - public ImageCreateResponse importImage(String repository, String tag, InputStream imageStream) throws DockerException { - Preconditions.checkNotNull(repository, "Repository was not specified"); - Preconditions.checkNotNull(imageStream, "imageStream was not provided"); - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("repo", repository); - params.add("tag", tag); - params.add("fromSrc","-"); - - WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params); - - try { - LOGGER.trace("POST: {}", webResource); - return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ImageCreateResponse.class,imageStream); - - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - } - - public List search(String search) throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + "/images/search").queryParam("term", search); - try { - return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - - } - - public void removeImage(String imageId) throws DockerException { - Preconditions.checkState(!StringUtils.isEmpty(imageId), "Image ID can't be empty"); - - try { - WebResource webResource = client.resource(restEndpointUrl + "/images/" + imageId); - LOGGER.trace("DELETE: {}", webResource); - webResource.delete(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully removed image " + imageId); - } else if (exception.getResponse().getStatus() == 404) { - LOGGER.warn("{} no such image", imageId); - } else if (exception.getResponse().getStatus() == 409) { - throw new DockerException("Conflict"); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error.", exception); - } else { - throw new DockerException(exception); - } - } - - } - - public void removeImages(List images) throws DockerException { - Preconditions.checkNotNull(images, "List of images can't be null"); - - for (String imageId : images) { - removeImage(imageId); - } - } - - public String getVizImages() throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + "/images/viz"); - - try { - LOGGER.trace("GET: {}", webResource); - String response = webResource.get(String.class); - LOGGER.trace("Response: {}", response); - - return response; - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 400) { - throw new DockerException("bad parameter"); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - - public List getImages() throws DockerException { - return this.getImages(null, false); - } - - public List getImages(boolean allContainers) throws DockerException { - return this.getImages(null, allContainers); - } - - public List getImages(String name) throws DockerException { - return this.getImages(name, false); - } - - public List getImages(String name, boolean allImages) throws DockerException { - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("filter", name); - params.add("all", allImages ? "1" : "0"); - - WebResource webResource = client.resource(restEndpointUrl + "/images/json").queryParams(params); - - try { - LOGGER.trace("GET: {}", webResource); - List images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response: {}", images); - return images; - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 400) { - throw new DockerException("bad parameter"); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(); - } - } - - } - - public ImageInspectResponse inspectImage(String imageId) throws DockerException, NotFoundException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); - - try { - LOGGER.trace("GET: {}", webResource); - return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such image %s", imageId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - /** - ** CONTAINER API - ** - **/ - - public List listContainers(boolean allContainers) { - return this.listContainers(allContainers, false, -1, false, null, null); - } - - public List listContainers(boolean allContainers, boolean latest) { - return this.listContainers(allContainers, latest, -1, false, null, null); - } - - public List listContainers(boolean allContainers, boolean latest, int limit) { - return this.listContainers(allContainers, latest, limit, false, null, null); - } - - public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize) { - return this.listContainers(allContainers, latest, limit, showSize, null, null); - } - - public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since) { - return this.listContainers(allContainers, latest, limit, false, since, null); - } - - public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since, String before) { - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("limit", latest ? "1" : String.valueOf(limit)); - params.add("all", allContainers ? "1" : "0"); - params.add("since", since); - params.add("before", before); - params.add("size", showSize ? "1" : "0"); - - WebResource webResource = client.resource(restEndpointUrl + "/containers/json").queryParams(params); - LOGGER.trace("GET: {}", webResource); - List containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response: {}", containers); - - return containers; - } - - public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException{ - return createContainer(config, null); - } - - public ContainerCreateResponse createContainer(ContainerConfig config,String name) throws DockerException, NotFoundException { - - MultivaluedMap params = new MultivaluedMapImpl(); - if(name != null){ - params.add("name", name); - } - WebResource webResource = client.resource(restEndpointUrl + "/containers/create").queryParams(params); - - try { - LOGGER.trace("POST: {} ", webResource); - return webResource.accept(MediaType.APPLICATION_JSON) - .type(MediaType.APPLICATION_JSON) - .post(ContainerCreateResponse.class, config); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage())); - } else if (exception.getResponse().getStatus() == 406) { - throw new DockerException("impossible to attach (container not running)"); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - - } - - public void startContainer(String containerId) throws DockerException { - this.startContainer(containerId, null); - } - - public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); - - try { - LOGGER.trace("POST: {}", webResource); - Builder builder = webResource.accept(MediaType.TEXT_PLAIN); - if (hostConfig != null) { - builder.type(MediaType.APPLICATION_JSON).post(hostConfig); - } else { - builder.post((HostConfig) null); - } - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully started container {}", containerId); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public ContainerInspectResponse inspectContainer(String containerId) throws DockerException, NotFoundException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); - - try { - LOGGER.trace("GET: {}", webResource); - return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - - public void removeContainer(String container) throws DockerException { - this.removeContainer(container, false); - } - - public void removeContainer(String containerId, boolean removeVolumes) throws DockerException { - Preconditions.checkState(!StringUtils.isEmpty(containerId), "Container ID can't be empty"); - - WebResource webResource = client.resource(restEndpointUrl + "/containers/" + containerId).queryParam("v", removeVolumes ? "1" : "0"); - - try { - LOGGER.trace("DELETE: {}", webResource); - String response = webResource.accept(MediaType.APPLICATION_JSON).delete(String.class); - LOGGER.trace("Response: {}", response); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully removed container " + containerId); - } else if (exception.getResponse().getStatus() == 400) { - throw new DockerException("bad parameter"); - } else if (exception.getResponse().getStatus() == 404) { - // should really throw a NotFoundException instead of silently ignoring the problem - LOGGER.warn(String.format("%s is an unrecognized container.", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - - public void removeContainers(List containers, boolean removeVolumes) throws DockerException { - Preconditions.checkNotNull(containers, "List of containers can't be null"); - - for (String containerId : containers) { - removeContainer(containerId, removeVolumes); - } - } - - public int waitContainer(String containerId) throws DockerException, NotFoundException { - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); - - try { - LOGGER.trace("POST: {}", webResource); - JSONObject jsonObject = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(JSONObject.class); - return jsonObject.getInt("StatusCode"); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } catch (JSONException e) { - throw new DockerException(e); - } - } - - - public ClientResponse logContainer(String containerId) throws DockerException { - return logContainer(containerId, false); - } - - public ClientResponse logContainerStream(String containerId) throws DockerException { - return logContainer(containerId, true); - } - - private ClientResponse logContainer(String containerId, boolean stream) throws DockerException, NotFoundException { - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("logs", "1"); - params.add("stdout", "1"); - params.add("stderr", "1"); - if (stream) { - params.add("stream", "1"); // this parameter keeps stream open indefinitely - } - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/attach", containerId)) - .queryParams(params); - - try { - LOGGER.trace("POST: {}", webResource); - return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class, params); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 400) { - throw new DockerException("bad parameter"); - } else if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public ClientResponse copyFile(String containerId, String resource) throws DockerException { - CopyConfig copyConfig = new CopyConfig(); - copyConfig.setResource(resource); - - WebResource webResource = - client.resource(restEndpointUrl + String.format("/containers/%s/copy", containerId)); - - try { - LOGGER.trace("POST: " + webResource.toString()); - WebResource.Builder builder = - webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).type("application/json"); - - return builder.post(ClientResponse.class, copyConfig.toString()); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 400) { - throw new DockerException("bad parameter"); - } else if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public List containerDiff(String containerId) throws DockerException, NotFoundException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); - - try { - LOGGER.trace("GET: {}", webResource); - return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - - - - public void stopContainer(String containerId) throws DockerException { - this.stopContainer(containerId, 10); - } - - public void stopContainer(String containerId, int timeout) throws DockerException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/stop", containerId)) - .queryParam("t", String.valueOf(timeout)); - - - try { - LOGGER.trace("POST: {}", webResource); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - LOGGER.warn("No such container {}", containerId); - } else if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully stopped container {}", containerId); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public void kill(String containerId) throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/kill", containerId)); - - try { - LOGGER.trace("POST: {}", webResource); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - LOGGER.warn("No such container {}", containerId); - } else if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully killed container {}", containerId); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public void restart(String containerId, int timeout) throws DockerException, NotFoundException { - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); - - try { - LOGGER.trace("POST: {}", webResource); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", containerId)); - } else if (exception.getResponse().getStatus() == 204) { - //no error - LOGGER.trace("Successfully restarted container {}", containerId); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } - } - - public String commit(CommitConfig commitConfig) throws DockerException, NotFoundException { - Preconditions.checkNotNull(commitConfig.getContainer(), "Container ID was not specified"); - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("container", commitConfig.getContainer()); - params.add("repo", commitConfig.getRepo()); - params.add("tag", commitConfig.getTag()); - params.add("m", commitConfig.getMessage()); - params.add("author", commitConfig.getAuthor()); - params.add("run", commitConfig.getRun()); - - WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params); - - try { - LOGGER.trace("POST: {}", webResource); - JSONObject jsonObject = webResource.accept("application/vnd.docker.raw-stream").post(JSONObject.class, params); - return jsonObject.getString("Id"); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer())); - } else if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } catch (JSONException e) { - throw new DockerException(e); - } - } - - - public ClientResponse build(File dockerFolder) throws DockerException { - return this.build(dockerFolder, null); - } - - public ClientResponse build(File dockerFolder, String tag) throws DockerException { - return this.build(dockerFolder, tag, false); - } - - public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException { - Preconditions.checkNotNull(dockerFolder, "Folder is null"); - Preconditions.checkArgument(dockerFolder.exists(), "Folder %s doesn't exist", dockerFolder); - Preconditions.checkState(new File(dockerFolder, "Dockerfile").exists(), "Dockerfile doesn't exist in " + dockerFolder); - - //We need to use Jersey HttpClient here, since ApacheHttpClient4 will not add boundary filed to - //Content-Type: multipart/form-data; boundary=Boundary_1_372491238_1372806136625 - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("t", tag); - if(noCache) { - params.add("nocache", "true"); - } - - // ARCHIVE TAR - String archiveNameWithOutExtension = UUID.randomUUID().toString(); - - File dockerFolderTar = null; - File tmpDockerContextFolder = null; - - try { - File dockerFile = new File(dockerFolder, "Dockerfile"); - List dockerFileContent = FileUtils.readLines(dockerFile); - - if (dockerFileContent.size() <= 0) { - throw new DockerException(String.format("Dockerfile %s is empty", dockerFile)); - } - - //Create tmp docker context folder - tmpDockerContextFolder = new File(FileUtils.getTempDirectoryPath(), "docker-java-build" + archiveNameWithOutExtension); - - FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder); - - for (String cmd : dockerFileContent) { - if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD")) { - String addArgs[] = StringUtils.split(cmd, " \t"); - if (addArgs.length != 3) { - throw new DockerException(String.format("Wrong format on line [%s]", cmd)); - } - - File src = new File(addArgs[1]); - if (!src.isAbsolute()) { - src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); - } - - if (!src.exists()) { - throw new DockerException(String.format("Source file %s doesnt' exist", src)); - } - if (src.isDirectory()) { - FileUtils.copyDirectoryToDirectory(src, tmpDockerContextFolder); - } else { - FileUtils.copyFileToDirectory(src, tmpDockerContextFolder); - } - } - } - - dockerFolderTar = CompressArchiveUtil.archiveTARFiles(tmpDockerContextFolder, archiveNameWithOutExtension); - - } catch (IOException ex) { - FileUtils.deleteQuietly(dockerFolderTar); - FileUtils.deleteQuietly(tmpDockerContextFolder); - throw new DockerException("Error occurred while preparing Docker context folder.", ex); - } - - WebResource webResource = client.resource(restEndpointUrl + "/build").queryParams(params); - - try { - LOGGER.trace("POST: {}", webResource); - return webResource - .type("application/tar") - .accept(MediaType.TEXT_PLAIN) - .post(ClientResponse.class, FileUtils.openInputStream(dockerFolderTar)); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 500) { - throw new DockerException("Server error", exception); - } else { - throw new DockerException(exception); - } - } catch (IOException e) { - throw new DockerException(e); - } finally { - FileUtils.deleteQuietly(dockerFolderTar); - FileUtils.deleteQuietly(tmpDockerContextFolder); - } - - } +public class DockerClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(DockerClient.class); + + private static DockerClient instance; + private Client client; + private String restEndpointUrl; + private AuthConfig authConfig; + + public DockerClient() { + this("http://localhost:4243"); + } + + public DockerClient(String serverUrl) { + restEndpointUrl = serverUrl + "/v1.10"; + ClientConfig clientConfig = new DefaultClientConfig(); + clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); + + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(new Scheme("http", 4243, PlainSocketFactory.getSocketFactory())); + schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory())); + + PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); + // Increase max total connection + cm.setMaxTotal(1000); + // Increase default max connection per route + cm.setDefaultMaxPerRoute(1000); + + HttpClient httpClient = new DefaultHttpClient(cm); + client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); + + //Experimental support for unix sockets: + //client = new UnixSocketClient(clientConfig); + + client.addFilter(new JsonClientFilter()); + client.addFilter(new LoggingFilter()); + } + + public void setCredentials(String username, String password, String email) { + if (username == null) { + throw new IllegalArgumentException("username is null"); + } + if (password == null) { + throw new IllegalArgumentException("password is null"); + } + if (email == null) { + throw new IllegalArgumentException("email is null"); + } + authConfig = new AuthConfig(); + authConfig.setUsername(username); + authConfig.setPassword(password); + authConfig.setEmail(email); + } + + /** + * Authenticate with the server, useful for checking authentication. + */ + public void auth() throws DockerException { + checkAuthConfig(); + try { + client.resource(restEndpointUrl + "/auth") + .header("Content-Type", MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .post(authConfig()); + } catch (UniformInterfaceException e) { + throw new DockerException(e); + } + } + + private String registryAuth() throws DockerException { + try { + return Base64.encodeBase64String(new ObjectMapper().writeValueAsString(authConfig()).getBytes()); + } catch (IOException e) { + throw new DockerException(e); + } + } + + private AuthConfig authConfig() throws DockerException { + checkAuthConfig(); + return authConfig; + } + + private void checkAuthConfig() throws DockerException { + if (authConfig == null) { + throw new DockerException("authentication credentials required"); + } + } + + /** + * * MISC API + * * + */ + + public Info info() throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/info"); + + try { + LOGGER.trace("GET: {}", webResource); + return webResource.accept(MediaType.APPLICATION_JSON).get(Info.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + } + + + public Version version() throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/version"); + + try { + LOGGER.trace("GET: {}", webResource); + return webResource.accept(MediaType.APPLICATION_JSON).get(Version.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + } + + + /** + * * IMAGE API + * * + */ + + public ClientResponse pull(String repository) throws DockerException { + return this.pull(repository, null, null); + } + + public ClientResponse pull(String repository, String tag) throws DockerException { + return this.pull(repository, tag, null); + } + + public ClientResponse pull(String repository, String tag, String registry) throws DockerException { + Preconditions.checkNotNull(repository, "Repository was not specified"); + + if (StringUtils.countMatches(repository, ":") == 1) { + String repositoryTag[] = StringUtils.split(repository); + repository = repositoryTag[0]; + tag = repositoryTag[1]; + + } + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("tag", tag); + params.add("fromImage", repository); + params.add("registry", registry); + + WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + } + + /** + * @return The output slurped into a string. + */ + public static String asString(ClientResponse response) throws IOException { + + StringWriter out = new StringWriter(); + try { + LineIterator itr = IOUtils.lineIterator( + response.getEntityInputStream(), "UTF-8"); + while (itr.hasNext()) { + String line = itr.next(); + out.write(line + "\n"); + } + } finally { + closeQuietly(response.getEntityInputStream()); + } + return out.toString(); + } + + /** + * Push the latest image to the repository. + * + * @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null. + */ + public void push(final String name) throws DockerException { + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + try { + final String registryAuth = registryAuth(); + client.resource(restEndpointUrl + "/images/" + name + "/push") + .header("X-Registry-Auth", registryAuth) + .accept(MediaType.APPLICATION_JSON) + .post(); + } catch (UniformInterfaceException e) { + throw new DockerException(e); + } + } + + /** + * Create an image by importing the given stream of a tar file. + * + * @param repository the repository to import to + * @param tag any tag for this image + * @param imageStream the InputStream of the tar file + * @return an {@link ImageCreateResponse} containing the id of the imported image + * @throws DockerException if the import fails for some reason. + */ + public ImageCreateResponse importImage(String repository, String tag, InputStream imageStream) throws DockerException { + Preconditions.checkNotNull(repository, "Repository was not specified"); + Preconditions.checkNotNull(imageStream, "imageStream was not provided"); + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("repo", repository); + params.add("tag", tag); + params.add("fromSrc", "-"); + + WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ImageCreateResponse.class, imageStream); + + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + } + + public List search(String search) throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/images/search").queryParam("term", search); + try { + return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() { + }); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + + } + + /** + * Remove an image, deleting any tags it might have. + */ + public void removeImage(String imageId) throws DockerException { + Preconditions.checkState(!StringUtils.isEmpty(imageId), "Image ID can't be empty"); + + try { + WebResource webResource = client.resource(restEndpointUrl + "/images/" + imageId) + .queryParam("force", "true"); + LOGGER.trace("DELETE: {}", webResource); + webResource.delete(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully removed image " + imageId); + } else if (exception.getResponse().getStatus() == 404) { + LOGGER.warn("{} no such image", imageId); + } else if (exception.getResponse().getStatus() == 409) { + throw new DockerException("Conflict"); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error.", exception); + } else { + throw new DockerException(exception); + } + } + + } + + public void removeImages(List images) throws DockerException { + Preconditions.checkNotNull(images, "List of images can't be null"); + + for (String imageId : images) { + removeImage(imageId); + } + } + + public String getVizImages() throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/images/viz"); + + try { + LOGGER.trace("GET: {}", webResource); + String response = webResource.get(String.class); + LOGGER.trace("Response: {}", response); + + return response; + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + + public List getImages() throws DockerException { + return this.getImages(null, false); + } + + public List getImages(boolean allContainers) throws DockerException { + return this.getImages(null, allContainers); + } + + public List getImages(String name) throws DockerException { + return this.getImages(name, false); + } + + public List getImages(String name, boolean allImages) throws DockerException { + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("filter", name); + params.add("all", allImages ? "1" : "0"); + + WebResource webResource = client.resource(restEndpointUrl + "/images/json").queryParams(params); + + try { + LOGGER.trace("GET: {}", webResource); + List images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() { + }); + LOGGER.trace("Response: {}", images); + return images; + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(); + } + } + + } + + public ImageInspectResponse inspectImage(String imageId) throws DockerException, NotFoundException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); + + try { + LOGGER.trace("GET: {}", webResource); + return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such image %s", imageId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + /** + * * CONTAINER API + * * + */ + + public List listContainers(boolean allContainers) { + return this.listContainers(allContainers, false, -1, false, null, null); + } + + public List listContainers(boolean allContainers, boolean latest) { + return this.listContainers(allContainers, latest, -1, false, null, null); + } + + public List listContainers(boolean allContainers, boolean latest, int limit) { + return this.listContainers(allContainers, latest, limit, false, null, null); + } + + public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize) { + return this.listContainers(allContainers, latest, limit, showSize, null, null); + } + + public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since) { + return this.listContainers(allContainers, latest, limit, false, since, null); + } + + public List listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since, String before) { + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("limit", latest ? "1" : String.valueOf(limit)); + params.add("all", allContainers ? "1" : "0"); + params.add("since", since); + params.add("before", before); + params.add("size", showSize ? "1" : "0"); + + WebResource webResource = client.resource(restEndpointUrl + "/containers/json").queryParams(params); + LOGGER.trace("GET: {}", webResource); + List containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() { + }); + LOGGER.trace("Response: {}", containers); + + return containers; + } + + public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException { + return createContainer(config, null); + } + + public ContainerCreateResponse createContainer(ContainerConfig config, String name) throws DockerException, NotFoundException { + + MultivaluedMap params = new MultivaluedMapImpl(); + if (name != null) { + params.add("name", name); + } + WebResource webResource = client.resource(restEndpointUrl + "/containers/create").queryParams(params); + + try { + LOGGER.trace("POST: {} ", webResource); + return webResource.accept(MediaType.APPLICATION_JSON) + .type(MediaType.APPLICATION_JSON) + .post(ContainerCreateResponse.class, config); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage())); + } else if (exception.getResponse().getStatus() == 406) { + throw new DockerException("impossible to attach (container not running)"); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + + } + + public void startContainer(String containerId) throws DockerException { + this.startContainer(containerId, null); + } + + public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); + + try { + LOGGER.trace("POST: {}", webResource); + Builder builder = webResource.accept(MediaType.TEXT_PLAIN); + if (hostConfig != null) { + builder.type(MediaType.APPLICATION_JSON).post(hostConfig); + } else { + builder.post((HostConfig) null); + } + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully started container {}", containerId); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public ContainerInspectResponse inspectContainer(String containerId) throws DockerException, NotFoundException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); + + try { + LOGGER.trace("GET: {}", webResource); + return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + + public void removeContainer(String container) throws DockerException { + this.removeContainer(container, false); + } + + public void removeContainer(String containerId, boolean removeVolumes) throws DockerException { + Preconditions.checkState(!StringUtils.isEmpty(containerId), "Container ID can't be empty"); + + WebResource webResource = client.resource(restEndpointUrl + "/containers/" + containerId).queryParam("v", removeVolumes ? "1" : "0"); + + try { + LOGGER.trace("DELETE: {}", webResource); + String response = webResource.accept(MediaType.APPLICATION_JSON).delete(String.class); + LOGGER.trace("Response: {}", response); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully removed container " + containerId); + } else if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 404) { + // should really throw a NotFoundException instead of silently ignoring the problem + LOGGER.warn(String.format("%s is an unrecognized container.", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + + public void removeContainers(List containers, boolean removeVolumes) throws DockerException { + Preconditions.checkNotNull(containers, "List of containers can't be null"); + + for (String containerId : containers) { + removeContainer(containerId, removeVolumes); + } + } + + public int waitContainer(String containerId) throws DockerException, NotFoundException { + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); + + try { + LOGGER.trace("POST: {}", webResource); + JSONObject jsonObject = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(JSONObject.class); + return jsonObject.getInt("StatusCode"); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } catch (JSONException e) { + throw new DockerException(e); + } + } + + + public ClientResponse logContainer(String containerId) throws DockerException { + return logContainer(containerId, false); + } + + public ClientResponse logContainerStream(String containerId) throws DockerException { + return logContainer(containerId, true); + } + + private ClientResponse logContainer(String containerId, boolean stream) throws DockerException, NotFoundException { + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("logs", "1"); + params.add("stdout", "1"); + params.add("stderr", "1"); + if (stream) { + params.add("stream", "1"); // this parameter keeps stream open indefinitely + } + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/attach", containerId)) + .queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class, params); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public ClientResponse copyFile(String containerId, String resource) throws DockerException { + CopyConfig copyConfig = new CopyConfig(); + copyConfig.setResource(resource); + + WebResource webResource = + client.resource(restEndpointUrl + String.format("/containers/%s/copy", containerId)); + + try { + LOGGER.trace("POST: " + webResource.toString()); + WebResource.Builder builder = + webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).type("application/json"); + + return builder.post(ClientResponse.class, copyConfig.toString()); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 400) { + throw new DockerException("bad parameter"); + } else if (exception.getResponse().getStatus() == 404) { + throw new DockerException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public List containerDiff(String containerId) throws DockerException, NotFoundException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); + + try { + LOGGER.trace("GET: {}", webResource); + return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() { + }); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + + public void stopContainer(String containerId) throws DockerException { + this.stopContainer(containerId, 10); + } + + public void stopContainer(String containerId, int timeout) throws DockerException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/stop", containerId)) + .queryParam("t", String.valueOf(timeout)); + + + try { + LOGGER.trace("POST: {}", webResource); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + LOGGER.warn("No such container {}", containerId); + } else if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully stopped container {}", containerId); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public void kill(String containerId) throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/kill", containerId)); + + try { + LOGGER.trace("POST: {}", webResource); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + LOGGER.warn("No such container {}", containerId); + } else if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully killed container {}", containerId); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public void restart(String containerId, int timeout) throws DockerException, NotFoundException { + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); + + try { + LOGGER.trace("POST: {}", webResource); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", containerId)); + } else if (exception.getResponse().getStatus() == 204) { + //no error + LOGGER.trace("Successfully restarted container {}", containerId); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } + } + + public String commit(CommitConfig commitConfig) throws DockerException, NotFoundException { + Preconditions.checkNotNull(commitConfig.getContainer(), "Container ID was not specified"); + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("container", commitConfig.getContainer()); + params.add("repo", commitConfig.getRepo()); + params.add("tag", commitConfig.getTag()); + params.add("m", commitConfig.getMessage()); + params.add("author", commitConfig.getAuthor()); + params.add("run", commitConfig.getRun()); + + WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + JSONObject jsonObject = webResource.accept("application/vnd.docker.raw-stream").post(JSONObject.class, params); + return jsonObject.getString("Id"); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer())); + } else if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } catch (JSONException e) { + throw new DockerException(e); + } + } + + + public ClientResponse build(File dockerFolder) throws DockerException { + return this.build(dockerFolder, null); + } + + public ClientResponse build(File dockerFolder, String tag) throws DockerException { + return this.build(dockerFolder, tag, false); + } + + public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException { + Preconditions.checkNotNull(dockerFolder, "Folder is null"); + Preconditions.checkArgument(dockerFolder.exists(), "Folder %s doesn't exist", dockerFolder); + Preconditions.checkState(new File(dockerFolder, "Dockerfile").exists(), "Dockerfile doesn't exist in " + dockerFolder); + + //We need to use Jersey HttpClient here, since ApacheHttpClient4 will not add boundary filed to + //Content-Type: multipart/form-data; boundary=Boundary_1_372491238_1372806136625 + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("t", tag); + if (noCache) { + params.add("nocache", "true"); + } + + // ARCHIVE TAR + String archiveNameWithOutExtension = UUID.randomUUID().toString(); + + File dockerFolderTar = null; + File tmpDockerContextFolder = null; + + try { + File dockerFile = new File(dockerFolder, "Dockerfile"); + List dockerFileContent = FileUtils.readLines(dockerFile); + + if (dockerFileContent.size() <= 0) { + throw new DockerException(String.format("Dockerfile %s is empty", dockerFile)); + } + + //Create tmp docker context folder + tmpDockerContextFolder = new File(FileUtils.getTempDirectoryPath(), "docker-java-build" + archiveNameWithOutExtension); + + FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder); + + for (String cmd : dockerFileContent) { + if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD")) { + String addArgs[] = StringUtils.split(cmd, " \t"); + if (addArgs.length != 3) { + throw new DockerException(String.format("Wrong format on line [%s]", cmd)); + } + + File src = new File(addArgs[1]); + if (!src.isAbsolute()) { + src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); + } + + if (!src.exists()) { + throw new DockerException(String.format("Source file %s doesnt' exist", src)); + } + if (src.isDirectory()) { + FileUtils.copyDirectoryToDirectory(src, tmpDockerContextFolder); + } else { + FileUtils.copyFileToDirectory(src, tmpDockerContextFolder); + } + } + } + + dockerFolderTar = CompressArchiveUtil.archiveTARFiles(tmpDockerContextFolder, archiveNameWithOutExtension); + + } catch (IOException ex) { + FileUtils.deleteQuietly(dockerFolderTar); + FileUtils.deleteQuietly(tmpDockerContextFolder); + throw new DockerException("Error occurred while preparing Docker context folder.", ex); + } + + WebResource webResource = client.resource(restEndpointUrl + "/build").queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + return webResource + .type("application/tar") + .accept(MediaType.TEXT_PLAIN) + .post(ClientResponse.class, FileUtils.openInputStream(dockerFolderTar)); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 500) { + throw new DockerException("Server error", exception); + } else { + throw new DockerException(exception); + } + } catch (IOException e) { + throw new DockerException(e); + } finally { + FileUtils.deleteQuietly(dockerFolderTar); + FileUtils.deleteQuietly(tmpDockerContextFolder); + } + + } } diff --git a/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java new file mode 100644 index 00000000..98de8965 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java @@ -0,0 +1,56 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class AuthConfig { + @JsonProperty + private String username; + @JsonProperty + private String password; + @JsonProperty + private String email; + @JsonProperty("serveraddress") + private String serverAddress = "https://index.docker.io/v1/"; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getServerAddress() { + return serverAddress; + } + + public void setServerAddress(String serverAddress) { + this.serverAddress = serverAddress; + } + + @Override + public String toString() { + return "AuthConfig{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", serverAddress='" + serverAddress + '\'' + + '}'; + } +} diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java new file mode 100644 index 00000000..8ac86149 --- /dev/null +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java @@ -0,0 +1,38 @@ +package com.kpelykh.docker.client.test; + + +import com.kpelykh.docker.client.DockerClient; +import com.kpelykh.docker.client.DockerException; +import com.sun.jersey.api.client.UniformInterfaceException; +import org.hamcrest.Matchers; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.testng.Assert.assertEquals; + +public class DockerClientAuthTest { + private DockerClient docker; + + @BeforeTest + public void beforeTest() throws Exception { + docker = new DockerClient(); + } + + @Test + public void testAuth() throws Exception { + docker.setCredentials("alexec", System.getProperty("password"), "alex.e.c@gmail.com"); + docker.auth(); + } + + @Test + public void testAuthInvalid() throws Exception { + docker.setCredentials("alexec", "XXXXX", "alex.e.c@gmail.com"); + try { + docker.auth(); + } catch (DockerException e) { + assertThat(e.getCause(), Matchers.instanceOf(UniformInterfaceException.class)); + assertEquals(401, ((UniformInterfaceException) e.getCause()).getResponse().getStatus()); + } + } +} diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java index fb20cb7e..98365588 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java @@ -1,7 +1,46 @@ package com.kpelykh.docker.client.test; -/** - * @author alexec (alex.e.c@gmail.com) - */ + +import com.kpelykh.docker.client.DockerClient; +import com.kpelykh.docker.client.DockerException; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static com.kpelykh.docker.client.DockerClient.asString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; + +// delete here : https://index.docker.io/u/alexec/busybox/delete/ public class DockerPushTest { + private DockerClient docker; + + @BeforeTest + public void beforeTest() throws Exception { + docker = new DockerClient(); + } + + @Test + public void testPushLatest() throws Exception { + setUpCredentials(); + docker.push("alexec/busybox"); + assertThat(asString(docker.pull("alexec/busybox")), not(containsString("404"))); + } + + @Test(expectedExceptions = DockerException.class) + public void testInvalidName() throws Exception { + setUpCredentials(); + docker.push("XXX"); + } + + @Test + public void testNotExistentImage() throws Exception { + setUpCredentials(); + docker.push("alexec/xxx"); + assertThat(asString(docker.pull("alexec/xxx")), containsString("404")); + } + + private void setUpCredentials() { + docker.setCredentials("alexec", System.getProperty("password"), "alex.e.c@gmail.com"); + } } From e418e2e00f41292d77d024ffda14656ef542eaf0 Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Sun, 27 Apr 2014 02:08:58 +0100 Subject: [PATCH 20/34] push support --- src/main/java/com/kpelykh/docker/client/DockerClient.java | 6 +++++- .../java/com/kpelykh/docker/client/test/DockerPushTest.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 108610e6..7681fd4f 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -242,7 +242,7 @@ public void push(final String name) throws DockerException { } try { final String registryAuth = registryAuth(); - client.resource(restEndpointUrl + "/images/" + name + "/push") + client.resource(restEndpointUrl + "/images/" + name(name) + "/push") .header("X-Registry-Auth", registryAuth) .accept(MediaType.APPLICATION_JSON) .post(); @@ -251,6 +251,10 @@ public void push(final String name) throws DockerException { } } + private String name(String name) { + return name.contains("/") ? name : authConfig.getUsername(); + } + /** * Create an image by importing the given stream of a tar file. * diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java index 98365588..cf7b9f73 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java @@ -23,7 +23,7 @@ public void beforeTest() throws Exception { @Test public void testPushLatest() throws Exception { setUpCredentials(); - docker.push("alexec/busybox"); + docker.push("busybox"); assertThat(asString(docker.pull("alexec/busybox")), not(containsString("404"))); } From a4103ca91a422869cba55c4d990b9e375aadb24d Mon Sep 17 00:00:00 2001 From: hack Date: Tue, 29 Apr 2014 21:16:11 +0200 Subject: [PATCH 21/34] Recover fix to testPullImage from commit 2a6d92da74343d7906ebfb0678eb7d3b1b8f5735, accidentally lost in 4ac45cd93ef94037331fee091ec6f004cf56ead8 --- .../com/kpelykh/docker/client/DockerClient.java | 2 +- .../docker/client/test/DockerClientTest.java | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 7681fd4f..70330af2 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -187,7 +187,7 @@ public ClientResponse pull(String repository, String tag, String registry) throw Preconditions.checkNotNull(repository, "Repository was not specified"); if (StringUtils.countMatches(repository, ":") == 1) { - String repositoryTag[] = StringUtils.split(repository); + String repositoryTag[] = StringUtils.split(repository, ':'); repository = repositoryTag[0]; tag = repositoryTag[1]; diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index affe0d96..8ceb74e7 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -474,7 +474,11 @@ public void removeContainer() throws DockerException { @Test public void testPullImage() throws DockerException, IOException { - String testImage = "kpelykh/vimbase"; + // This should be an image that is not used by other repositories already + // pulled down, preferably small in size. If tag is not used pull will + // download all images in that repository but tmpImgs will only + // deleted 'latest' image but not images with other tags + String testImage = "hackmann/empty"; LOG.info("Removing image: {}", testImage); dockerClient.removeImage(testImage); @@ -486,6 +490,7 @@ public void testPullImage() throws DockerException, IOException { LOG.info("Pulling image: {}", testImage); + tmpImgs.add(testImage); ClientResponse response = dockerClient.pull(testImage); StringWriter logwriter = new StringWriter(); @@ -503,15 +508,12 @@ public void testPullImage() throws DockerException, IOException { } String fullLog = logwriter.toString(); - assertThat(fullLog, - containsString("Pulling repository kpelykh/vimbase")); - - tmpImgs.add(testImage); + assertThat(fullLog, containsString("Download complete")); info = dockerClient.info(); LOG.info("Client info after pull, {}", info.toString()); - assertThat(imgCount + 1, equalTo(info.getImages())); + assertThat(imgCount, lessThan(info.getImages())); ImageInspectResponse imageInspectResponse = dockerClient .inspectImage(testImage); From acd9754542dadedca802fb59b34becbd610333f1 Mon Sep 17 00:00:00 2001 From: hack Date: Tue, 29 Apr 2014 22:38:41 +0200 Subject: [PATCH 22/34] Change how a tarball is generated when sending a build request. Instead of creating a temporary folder and copying all the files in a flat structure, read the files directly and preserve their path details. Fixes a problem with adding files in a subfolder like: Step 2 : ADD files/authorized_keys /var/lib/jenkins/.ssh/ [Docker] ERROR: {"errorDetail":{"message":"files/authorized_keys: no such file or directory"},"error":"files/authorized_keys: no such file or directory"} --- .../kpelykh/docker/client/DockerClient.java | 20 +++----- .../client/utils/CompressArchiveUtil.java | 49 ++++++------------- .../docker/client/test/DockerClientTest.java | 15 ++++-- .../testAddFileInSubfolder/Dockerfile | 9 ++++ .../testAddFileInSubfolder/files/testrun.sh | 3 ++ 5 files changed, 45 insertions(+), 51 deletions(-) create mode 100644 src/test/resources/testAddFileInSubfolder/Dockerfile create mode 100755 src/test/resources/testAddFileInSubfolder/files/testrun.sh diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 70330af2..4158dc58 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -805,7 +806,6 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro String archiveNameWithOutExtension = UUID.randomUUID().toString(); File dockerFolderTar = null; - File tmpDockerContextFolder = null; try { File dockerFile = new File(dockerFolder, "Dockerfile"); @@ -815,10 +815,8 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro throw new DockerException(String.format("Dockerfile %s is empty", dockerFile)); } - //Create tmp docker context folder - tmpDockerContextFolder = new File(FileUtils.getTempDirectoryPath(), "docker-java-build" + archiveNameWithOutExtension); - - FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder); + List filesToAdd = new ArrayList(); + filesToAdd.add(dockerFile); for (String cmd : dockerFileContent) { if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD")) { @@ -833,21 +831,20 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro } if (!src.exists()) { - throw new DockerException(String.format("Source file %s doesnt' exist", src)); + throw new DockerException(String.format("Source file %s doesn't exist", src)); } if (src.isDirectory()) { - FileUtils.copyDirectoryToDirectory(src, tmpDockerContextFolder); + filesToAdd.addAll(FileUtils.listFiles(src, null, true)); } else { - FileUtils.copyFileToDirectory(src, tmpDockerContextFolder); + filesToAdd.add(src); } } } - dockerFolderTar = CompressArchiveUtil.archiveTARFiles(tmpDockerContextFolder, archiveNameWithOutExtension); + dockerFolderTar = CompressArchiveUtil.archiveTARFiles(dockerFolder, filesToAdd, archiveNameWithOutExtension); } catch (IOException ex) { FileUtils.deleteQuietly(dockerFolderTar); - FileUtils.deleteQuietly(tmpDockerContextFolder); throw new DockerException("Error occurred while preparing Docker context folder.", ex); } @@ -869,9 +866,6 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro throw new DockerException(e); } finally { FileUtils.deleteQuietly(dockerFolderTar); - FileUtils.deleteQuietly(tmpDockerContextFolder); } - } - } diff --git a/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java b/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java index 502ad0b7..aabf4cbb 100644 --- a/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java +++ b/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java @@ -3,57 +3,36 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.RegexFileFilter; -import org.apache.commons.lang.StringUtils; import java.io.*; -import java.util.Collection; - -import static org.apache.commons.io.filefilter.FileFilterUtils.*; public class CompressArchiveUtil { - public static File archiveTARFiles(File baseDir, String archiveNameWithOutExtension) throws IOException { - - File tarFile = null; - - tarFile = new File(FileUtils.getTempDirectoryPath(), archiveNameWithOutExtension + ".tar"); - - Collection files = - FileUtils.listFiles( - baseDir, - new RegexFileFilter("^(.*?)"), - and(directoryFileFilter(), notFileFilter(nameFileFilter(baseDir.getName())))); - - byte[] buf = new byte[1024]; - int len; - - { - TarArchiveOutputStream tos = new TarArchiveOutputStream(new FileOutputStream(tarFile)); + public static File archiveTARFiles(File base, Iterable files, String archiveNameWithOutExtension) throws IOException { + File tarFile = new File(FileUtils.getTempDirectoryPath(), archiveNameWithOutExtension + ".tar"); + TarArchiveOutputStream tos = new TarArchiveOutputStream(new FileOutputStream(tarFile)); + try { tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); for (File file : files) { TarArchiveEntry tarEntry = new TarArchiveEntry(file); - tarEntry.setName(StringUtils.substringAfter(file.toString(), baseDir.getPath())); + tarEntry.setName(relativize(base, file)); tos.putArchiveEntry(tarEntry); if (!file.isDirectory()) { - FileInputStream fin = new FileInputStream(file); - BufferedInputStream in = new BufferedInputStream(fin); - - while ((len = in.read(buf)) != -1) { - tos.write(buf, 0, len); - } - - in.close(); + FileUtils.copyFile(file, tos); } tos.closeArchiveEntry(); - } + } finally { tos.close(); } - - return tarFile; - } + return tarFile; + } + + private static String relativize(File base, File absolute) { + String relative = base.toURI().relativize(absolute.toURI()).getPath(); + return relative; + } } diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index 8ceb74e7..b4fd2f2d 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -40,8 +40,8 @@ public class DockerClientTest extends Assert { private DockerClient dockerClient; - private List tmpImgs = new ArrayList(); - private List tmpContainers = new ArrayList(); + private List tmpImgs; + private List tmpContainers; @BeforeTest public void beforeTest() throws DockerException { @@ -64,6 +64,8 @@ public void afterTest() { @BeforeMethod public void beforeMethod(Method method) { + tmpContainers = new ArrayList(); + tmpImgs = new ArrayList(); LOG.info(String .format("################################## STARTING %s ##################################", method.getName())); @@ -663,7 +665,14 @@ public void testDockerBuilderAddFile() throws DockerException, IOException { dockerfileBuild(baseDir, "Successfully executed testrun.sh"); } - @Test + @Test + public void testDockerBuilderAddFileInSubfolder() throws DockerException, IOException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("testAddFileInSubfolder").getFile()); + dockerfileBuild(baseDir, "Successfully executed testrun.sh"); + } + + @Test public void testDockerBuilderAddFolder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader() diff --git a/src/test/resources/testAddFileInSubfolder/Dockerfile b/src/test/resources/testAddFileInSubfolder/Dockerfile new file mode 100644 index 00000000..41d8f437 --- /dev/null +++ b/src/test/resources/testAddFileInSubfolder/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu + +# Copy testrun.sh files into the container + +ADD ./files/testrun.sh /tmp/ + +RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh + +CMD ["testrun.sh"] diff --git a/src/test/resources/testAddFileInSubfolder/files/testrun.sh b/src/test/resources/testAddFileInSubfolder/files/testrun.sh new file mode 100755 index 00000000..80b468e7 --- /dev/null +++ b/src/test/resources/testAddFileInSubfolder/files/testrun.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Successfully executed testrun.sh" From 15eed5cdd45b4aec54cb285f37f4fda909e5d956 Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Thu, 8 May 2014 19:27:12 +0100 Subject: [PATCH 23/34] scm --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 4b4b2215..373c47f4 100644 --- a/pom.xml +++ b/pom.xml @@ -25,9 +25,9 @@ - scm:git:git@github.com:kpelykh/docker-java.git - git@github.com:kpelykh/docker-java.git - scm:git:git@github.com:kpelykh/docker-java.git + scm:git:git@github.com:alexec/docker-java.git + git@github.com:alexec/docker-java.git + scm:git:git@github.com:alexec/docker-java.git HEAD From 17eb43e3869fe7325a3178e07a17e837865ddb72 Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Tue, 13 May 2014 22:47:20 +0100 Subject: [PATCH 24/34] removed SNAPSHOT contraint --- pom.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pom.xml b/pom.xml index 373c47f4..ffcc8f53 100644 --- a/pom.xml +++ b/pom.xml @@ -193,6 +193,21 @@ test + + + + com.github.jnr + jffi + 1.2.7 + + + com.github.jnr + jffi + native + 1.2.7 + + + From 88b06be36a7384e245a19aae557220dba5fb8d6b Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 16 May 2014 23:01:23 +0200 Subject: [PATCH 25/34] Merged push image functionality. --- README.md | 4 +- pom.xml | 9 +- .../kpelykh/docker/client/DockerClient.java | 11 +- .../docker/client/model/AuthConfig.java | 2 + .../docker/client/model/ChangeLog.java | 2 + .../docker/client/model/CommitConfig.java | 2 + .../docker/client/model/ContainerConfig.java | 2 + .../client/model/ContainerCreateResponse.java | 2 + .../model/ContainerInspectResponse.java | 18 +- .../docker/client/model/CopyConfig.java | 2 + .../docker/client/model/DriverStatus.java | 2 + .../docker/client/model/HostConfig.java | 2 + .../kpelykh/docker/client/model/Image.java | 2 + .../client/model/ImageCreateResponse.java | 4 +- .../client/model/ImageInspectResponse.java | 2 + .../com/kpelykh/docker/client/model/Info.java | 2 + .../com/kpelykh/docker/client/model/Port.java | 3 +- .../docker/client/model/SearchItem.java | 2 + .../kpelykh/docker/client/model/Version.java | 3 +- .../client/test/AbstractDockerClientTest.java | 103 ++++++++++ .../client/test/DockerClientAuthTest.java | 44 +++-- .../docker/client/test/DockerClientTest.java | 176 ++++++------------ .../docker/client/test/DockerPushTest.java | 86 +++++++-- 23 files changed, 320 insertions(+), 165 deletions(-) create mode 100644 src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java diff --git a/README.md b/README.md index e301faef..76075d2f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") -Supports a subset of the Docker Client API v1.10, Docker Server version 0.10 +Supports a subset of the Docker Client API v1.11, Docker Server version 0.11 + +Developer forum for [docker-java](https://groups.google.com/forum/?hl=de#!forum/docker-java-dev "docker-java") ## Build with Maven diff --git a/pom.xml b/pom.xml index ffcc8f53..a7390017 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 7 - com.alexecollins + com.kpelykh docker-java jar 0.8.2-SNAPSHOT @@ -25,10 +25,9 @@ - scm:git:git@github.com:alexec/docker-java.git - git@github.com:alexec/docker-java.git - scm:git:git@github.com:alexec/docker-java.git - HEAD + scm:git:git@github.com:kpelykh/docker-java.git + git@github.com:kpelykh/docker-java.git + scm:git:git@github.com:kpelykh/docker-java.git diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 4158dc58..1f606922 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -60,7 +60,7 @@ public DockerClient() { } public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.10"; + restEndpointUrl = serverUrl + "/v1.11"; ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); @@ -77,6 +77,7 @@ public DockerClient(String serverUrl) { HttpClient httpClient = new DefaultHttpClient(cm); client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); + client.setReadTimeout(10000); //Experimental support for unix sockets: //client = new UnixSocketClient(clientConfig); @@ -224,7 +225,7 @@ public static String asString(ClientResponse response) throws IOException { response.getEntityInputStream(), "UTF-8"); while (itr.hasNext()) { String line = itr.next(); - out.write(line + "\n"); + out.write(line + (itr.hasNext() ? "\n" : "")); } } finally { closeQuietly(response.getEntityInputStream()); @@ -237,16 +238,16 @@ public static String asString(ClientResponse response) throws IOException { * * @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null. */ - public void push(final String name) throws DockerException { + public ClientResponse push(final String name) throws DockerException { if (name == null) { throw new IllegalArgumentException("name is null"); } try { final String registryAuth = registryAuth(); - client.resource(restEndpointUrl + "/images/" + name(name) + "/push") + return client.resource(restEndpointUrl + "/images/" + name(name) + "/push") .header("X-Registry-Auth", registryAuth) .accept(MediaType.APPLICATION_JSON) - .post(); + .post(ClientResponse.class); } catch (UniformInterfaceException e) { throw new DockerException(e); } diff --git a/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java index 98de8965..3fc709f7 100644 --- a/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java @@ -1,7 +1,9 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; +@JsonIgnoreProperties(ignoreUnknown = true) public class AuthConfig { @JsonProperty private String username; diff --git a/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java index be6df3a4..ac45ad3e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java +++ b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** @@ -7,6 +8,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ChangeLog { @JsonProperty("Path") diff --git a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java index 69af9959..51a83d8e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** @@ -7,6 +8,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class CommitConfig { @JsonProperty("container") diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java index f3a7d344..5e9dbf7d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import java.util.Arrays; @@ -10,6 +11,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ContainerConfig { @JsonProperty("Hostname") private String hostName = ""; diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java index d56d6773..43b6144d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import java.util.Arrays; @@ -9,6 +10,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ContainerCreateResponse { @JsonProperty("Id") diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java index f86fc481..55db87e3 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -1,16 +1,17 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonProperty; - -import java.util.Arrays; import java.util.Map; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.annotate.JsonProperty; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ContainerInspectResponse { @JsonProperty("ID") @@ -67,6 +68,9 @@ public class ContainerInspectResponse { @JsonProperty("ExecDriver") private String execDriver; + @JsonProperty("MountLabel") + private String mountLabel; + public String getId() { return id; } @@ -210,6 +214,14 @@ public void setExecDriver(String execDriver) { public String getExecDriver() { return execDriver; } + + public String getMountLabel() { + return mountLabel; + } + + public void setMountLabel(String mountLabel) { + this.mountLabel = mountLabel; + } public class NetworkSettings { diff --git a/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java index f94106cb..7fea11fc 100755 --- a/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java @@ -1,11 +1,13 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** * Configuration object for copy command. * @author Victor Lyuboslavsky */ +@JsonIgnoreProperties(ignoreUnknown = true) public class CopyConfig { @JsonProperty("HostPath") diff --git a/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java index 2ed1922c..3968efc1 100644 --- a/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java +++ b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java @@ -1,10 +1,12 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** * Created by ben on 12/12/13. */ +@JsonIgnoreProperties(ignoreUnknown = true) public class DriverStatus { @JsonProperty("Root Dir") diff --git a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java index c2484f78..ec6a043e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import java.util.Arrays; @@ -9,6 +10,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class HostConfig { @JsonProperty("Binds") diff --git a/src/main/java/com/kpelykh/docker/client/model/Image.java b/src/main/java/com/kpelykh/docker/client/model/Image.java index 4b68590c..a6a1a18f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Image.java +++ b/src/main/java/com/kpelykh/docker/client/model/Image.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import java.util.Arrays; @@ -9,6 +10,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class Image { @JsonProperty("Id") diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java index 4be68072..26d83400 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java @@ -1,15 +1,15 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; -import java.util.Arrays; - /** * Parse reponses from /images/create * * @author Ryan Campbell (ryan.campbell@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ImageCreateResponse { @JsonProperty("status") diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java index 4b714f4f..187cf5c3 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** @@ -7,6 +8,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class ImageInspectResponse { @JsonProperty("id") diff --git a/src/main/java/com/kpelykh/docker/client/model/Info.java b/src/main/java/com/kpelykh/docker/client/model/Info.java index 6fcb9f2c..59e9e9ed 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.map.annotate.JsonSerialize; @@ -11,6 +12,7 @@ * */ @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) public class Info { @JsonProperty("Debug") diff --git a/src/main/java/com/kpelykh/docker/client/model/Port.java b/src/main/java/com/kpelykh/docker/client/model/Port.java index b4fa913a..048c2ab5 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Port.java +++ b/src/main/java/com/kpelykh/docker/client/model/Port.java @@ -1,11 +1,12 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** * @author Nicolas De Loof */ - +@JsonIgnoreProperties(ignoreUnknown = true) public class Port { @JsonProperty("PrivatePort") diff --git a/src/main/java/com/kpelykh/docker/client/model/SearchItem.java b/src/main/java/com/kpelykh/docker/client/model/SearchItem.java index 9c0942ea..8478a321 100644 --- a/src/main/java/com/kpelykh/docker/client/model/SearchItem.java +++ b/src/main/java/com/kpelykh/docker/client/model/SearchItem.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** @@ -7,6 +8,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class SearchItem { @JsonProperty("star_count") diff --git a/src/main/java/com/kpelykh/docker/client/model/Version.java b/src/main/java/com/kpelykh/docker/client/model/Version.java index 6937495f..d8d27b39 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -1,5 +1,6 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; /** @@ -7,9 +8,9 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown = true) public class Version { - @JsonProperty("Version") private String version; diff --git a/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java new file mode 100644 index 00000000..eb9bcf73 --- /dev/null +++ b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java @@ -0,0 +1,103 @@ +package com.kpelykh.docker.client.test; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.ITestResult; + +import com.kpelykh.docker.client.DockerClient; +import com.kpelykh.docker.client.DockerException; +import com.sun.jersey.api.client.ClientResponse; + +public abstract class AbstractDockerClientTest extends Assert { + + public static final Logger LOG = LoggerFactory + .getLogger(AbstractDockerClientTest.class); + + protected DockerClient dockerClient; + + protected List tmpImgs; + protected List tmpContainers; + + + public void beforeTest() throws DockerException { + LOG.info("======================= BEFORETEST ======================="); + String url = System.getProperty("docker.url", "http://localhost:4243"); + LOG.info("Connecting to Docker server at " + url); + dockerClient = new DockerClient(url); + + LOG.info("Creating image 'busybox'"); + dockerClient.pull("busybox"); + + assertNotNull(dockerClient); + LOG.info("======================= END OF BEFORETEST =======================\n\n"); + } + + public void afterTest() { + LOG.info("======================= END OF AFTERTEST ======================="); + } + + + public void beforeMethod(Method method) { + tmpContainers = new ArrayList(); + tmpImgs = new ArrayList(); + LOG.info(String + .format("################################## STARTING %s ##################################", + method.getName())); + } + + public void afterMethod(ITestResult result) { + + for (String container : tmpContainers) { + LOG.info("Cleaning up temporary container {}", container); + try { + dockerClient.stopContainer(container); + dockerClient.kill(container); + dockerClient.removeContainer(container); + } catch (DockerException ignore) { + } + } + + for (String image : tmpImgs) { + LOG.info("Cleaning up temporary image {}", image); + try { + dockerClient.removeImage(image); + } catch (DockerException ignore) { + } + } + + LOG.info( + "################################## END OF {} ##################################\n", + result.getName()); + } + + protected String logResponseStream(ClientResponse response) throws IOException { + String responseString = DockerClient.asString(response); + LOG.info("Container log: {}", responseString); + return responseString; + } + + private String getProperty(String name) { + String property = System.getProperty(name); + if(property == null || property.isEmpty()) throw new RuntimeException("Need to configure '" + name + "' property to run the test. Use command line option -D"+ name +"=... to do so."); + return property; + } + + protected String getUsername() { + return getProperty("docker.io.username"); + } + + protected String getPassword() { + return getProperty("docker.io.password"); + } + + protected String getEmail() { + return getProperty("docker.io.email"); + } + +} diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java index 8ac86149..6fe6e999 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java @@ -1,35 +1,53 @@ package com.kpelykh.docker.client.test; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.lang.reflect.Method; +import java.util.ArrayList; -import com.kpelykh.docker.client.DockerClient; -import com.kpelykh.docker.client.DockerException; -import com.sun.jersey.api.client.UniformInterfaceException; import org.hamcrest.Matchers; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.testng.Assert.assertEquals; +import com.kpelykh.docker.client.DockerException; +import com.sun.jersey.api.client.UniformInterfaceException; -public class DockerClientAuthTest { - private DockerClient docker; +public class DockerClientAuthTest extends AbstractDockerClientTest { @BeforeTest - public void beforeTest() throws Exception { - docker = new DockerClient(); + public void beforeTest() throws DockerException { + super.beforeTest(); + } + @AfterTest + public void afterTest() { + super.afterTest(); } + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + super.afterMethod(result); + } + @Test public void testAuth() throws Exception { - docker.setCredentials("alexec", System.getProperty("password"), "alex.e.c@gmail.com"); - docker.auth(); + dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); + dockerClient.auth(); } @Test public void testAuthInvalid() throws Exception { - docker.setCredentials("alexec", "XXXXX", "alex.e.c@gmail.com"); + dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); try { - docker.auth(); + dockerClient.auth(); } catch (DockerException e) { assertThat(e.getCause(), Matchers.instanceOf(UniformInterfaceException.class)); assertEquals(401, ((UniformInterfaceException) e.getCause()).getResponse().getStatus()); diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index b4fd2f2d..89e83a88 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -1,18 +1,22 @@ package com.kpelykh.docker.client.test; -import com.kpelykh.docker.client.DockerClient; -import com.kpelykh.docker.client.DockerException; -import com.kpelykh.docker.client.model.*; -import com.sun.jersey.api.client.ClientResponse; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.LineIterator; -import org.apache.commons.lang.StringUtils; -import org.hamcrest.Matcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.ITestResult; -import org.testng.annotations.*; +import static ch.lambdaj.Lambda.filter; +import static ch.lambdaj.Lambda.selectUnique; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.startsWith; +import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField; import java.io.File; import java.io.IOException; @@ -20,81 +24,62 @@ import java.lang.reflect.Method; import java.net.DatagramSocket; import java.net.ServerSocket; -import java.util.ArrayList; import java.util.List; -import static ch.lambdaj.Lambda.filter; -import static ch.lambdaj.Lambda.selectUnique; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField; +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.LineIterator; +import org.apache.commons.lang.StringUtils; +import org.hamcrest.Matcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.kpelykh.docker.client.DockerException; +import com.kpelykh.docker.client.model.ChangeLog; +import com.kpelykh.docker.client.model.CommitConfig; +import com.kpelykh.docker.client.model.Container; +import com.kpelykh.docker.client.model.ContainerConfig; +import com.kpelykh.docker.client.model.ContainerCreateResponse; +import com.kpelykh.docker.client.model.ContainerInspectResponse; +import com.kpelykh.docker.client.model.Image; +import com.kpelykh.docker.client.model.ImageInspectResponse; +import com.kpelykh.docker.client.model.Info; +import com.kpelykh.docker.client.model.Ports; +import com.kpelykh.docker.client.model.SearchItem; +import com.kpelykh.docker.client.model.Version; +import com.sun.jersey.api.client.ClientResponse; /** * Unit test for DockerClient. * * @author Konstantin Pelykh (kpelykh@gmail.com) */ -public class DockerClientTest extends Assert { +public class DockerClientTest extends AbstractDockerClientTest { public static final Logger LOG = LoggerFactory .getLogger(DockerClientTest.class); - private DockerClient dockerClient; - - private List tmpImgs; - private List tmpContainers; - @BeforeTest public void beforeTest() throws DockerException { - LOG.info("======================= BEFORETEST ======================="); - String url = System.getProperty("docker.url", "http://localhost:4243"); - LOG.info("Connecting to Docker server at " + url); - dockerClient = new DockerClient(url); - - LOG.info("Creating image 'busybox'"); - dockerClient.pull("busybox"); - - assertNotNull(dockerClient); - LOG.info("======================= END OF BEFORETEST =======================\n\n"); + super.beforeTest(); } - @AfterTest public void afterTest() { - LOG.info("======================= END OF AFTERTEST ======================="); + super.afterTest(); } @BeforeMethod public void beforeMethod(Method method) { - tmpContainers = new ArrayList(); - tmpImgs = new ArrayList(); - LOG.info(String - .format("################################## STARTING %s ##################################", - method.getName())); + super.beforeMethod(method); } @AfterMethod public void afterMethod(ITestResult result) { - - for (String container : tmpContainers) { - LOG.info("Cleaning up temporary container {}", container); - try { - dockerClient.stopContainer(container); - dockerClient.kill(container); - dockerClient.removeContainer(container); - } catch (DockerException ignore) { - } - } - - for (String image : tmpImgs) { - LOG.info("Cleaning up temporary image {}", image); - try { - dockerClient.removeImage(image); - } catch (DockerException ignore) { - } - } - - LOG.info( - "################################## END OF {} ##################################\n", - result.getName()); + super.afterMethod(result); } /* @@ -181,6 +166,8 @@ public void testListContainers() throws DockerException { assertThat(container1.getId(), not(isEmptyString())); dockerClient.startContainer(container1.getId()); tmpContainers.add(container1.getId()); + + LOG.info("container id: " + container1.getId()); List containers2 = dockerClient.listContainers(true); assertThat(size + 1, is(equalTo(containers2.size()))); @@ -191,6 +178,10 @@ public void testListContainers() throws DockerException { hasField("id", startsWith(container1.getId())), containers2); assertThat(filteredContainers.size(), is(equalTo(1))); + for(Container container: filteredContainers) { + LOG.info("container: " + container); + } + Container container2 = filteredContainers.get(0); assertThat(container2.getCommand(), not(isEmptyString())); assertThat(container2.getImage(), equalTo("busybox:latest")); @@ -307,24 +298,7 @@ public void testLogs() throws DockerException, IOException { ClientResponse response = dockerClient.logContainer(container.getId()); - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator( - response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + (itr.hasNext() ? "\n" : "")); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - String fullLog = logwriter.toString(); - - LOG.info("Container log: {}", fullLog); - assertThat(fullLog, endsWith(snippet)); + assertThat(logResponseStream(response), endsWith(snippet)); } @Test @@ -345,7 +319,7 @@ public void testDiff() throws DockerException { List filesystemDiff = dockerClient.containerDiff(container.getId()); LOG.info("Container DIFF: {}", filesystemDiff.toString()); - assertThat(filesystemDiff.size(), equalTo(4)); + assertThat(filesystemDiff.size(), equalTo(1)); ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); @@ -495,27 +469,13 @@ public void testPullImage() throws DockerException, IOException { tmpImgs.add(testImage); ClientResponse response = dockerClient.pull(testImage); - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator( - response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line + "\n"); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Download complete")); + assertThat(logResponseStream(response), containsString("Download complete")); info = dockerClient.info(); LOG.info("Client info after pull, {}", info.toString()); - assertThat(imgCount, lessThan(info.getImages())); + // TODO: imgCount should differ (maybe a docker bug?) + assertThat(imgCount, lessThanOrEqualTo(info.getImages())); ImageInspectResponse imageInspectResponse = dockerClient .inspectImage(testImage); @@ -825,21 +785,7 @@ private String dockerfileBuild(File baseDir, String expectedText) ClientResponse logResponse = dockerClient.logContainer(container .getId()); - StringWriter logwriter2 = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator( - logResponse.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter2.write(line + (itr.hasNext() ? "\n" : "")); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(logResponse.getEntityInputStream()); - } - - assertThat(logwriter2.toString(), endsWith(expectedText)); + assertThat(logResponseStream(logResponse), endsWith(expectedText)); return container.getId(); } diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java index cf7b9f73..b5709f96 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java @@ -1,46 +1,94 @@ package com.kpelykh.docker.client.test; -import com.kpelykh.docker.client.DockerClient; -import com.kpelykh.docker.client.DockerException; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - import static com.kpelykh.docker.client.DockerClient.asString; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import com.kpelykh.docker.client.DockerException; +import com.kpelykh.docker.client.model.CommitConfig; +import com.kpelykh.docker.client.model.ContainerConfig; +import com.kpelykh.docker.client.model.ContainerCreateResponse; + // delete here : https://index.docker.io/u/alexec/busybox/delete/ -public class DockerPushTest { - private DockerClient docker; +public class DockerPushTest extends AbstractDockerClientTest { + + public static final Logger LOG = LoggerFactory + .getLogger(DockerPushTest.class); @BeforeTest - public void beforeTest() throws Exception { - docker = new DockerClient(); + public void beforeTest() throws DockerException { + super.beforeTest(); + } + @AfterTest + public void afterTest() { + super.afterTest(); } + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + super.afterMethod(result); + } + @Test public void testPushLatest() throws Exception { setUpCredentials(); - docker.push("busybox"); - assertThat(asString(docker.pull("alexec/busybox")), not(containsString("404"))); - } + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] { "true" }); - @Test(expectedExceptions = DockerException.class) - public void testInvalidName() throws Exception { - setUpCredentials(); - docker.push("XXX"); + ContainerCreateResponse container = dockerClient + .createContainer(containerConfig); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + tmpContainers.add(container.getId()); + + LOG.info("Commiting container: {}", container.toString()); + CommitConfig commitConfig = new CommitConfig(container.getId()); + commitConfig.setRepo(getUsername() + "/busybox"); + + String imageId = dockerClient + .commit(commitConfig); + + logResponseStream(dockerClient.push(getUsername() + "/busybox")); + + dockerClient.removeImage(imageId); + + assertThat(asString(dockerClient.pull(getUsername() + "/busybox")), not(containsString("404"))); } @Test public void testNotExistentImage() throws Exception { setUpCredentials(); - docker.push("alexec/xxx"); - assertThat(asString(docker.pull("alexec/xxx")), containsString("404")); + assertThat(logResponseStream(dockerClient.push(getUsername() + "/xxx")), containsString("error")); } private void setUpCredentials() { - docker.setCredentials("alexec", System.getProperty("password"), "alex.e.c@gmail.com"); + dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); } + + } + From 98b265515b152822fc9a28e598ceb150bf6a892a Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Sat, 17 May 2014 13:10:55 +0200 Subject: [PATCH 26/34] Upgraded from jersey-json to jackson-jaxrs 2.3.3 --- pom.xml | 189 +++++++++--------- .../kpelykh/docker/client/DockerClient.java | 22 +- .../docker/client/model/AuthConfig.java | 4 +- .../docker/client/model/BoundHostVolumes.java | 11 +- .../docker/client/model/ChangeLog.java | 4 +- .../docker/client/model/CommitConfig.java | 4 +- .../docker/client/model/Container.java | 4 +- .../docker/client/model/ContainerConfig.java | 4 +- .../client/model/ContainerCreateResponse.java | 4 +- .../model/ContainerInspectResponse.java | 4 +- .../docker/client/model/CopyConfig.java | 4 +- .../docker/client/model/DriverStatus.java | 4 +- .../docker/client/model/HostConfig.java | 4 +- .../kpelykh/docker/client/model/Image.java | 4 +- .../client/model/ImageCreateResponse.java | 4 +- .../client/model/ImageInspectResponse.java | 4 +- .../com/kpelykh/docker/client/model/Info.java | 6 +- .../com/kpelykh/docker/client/model/Port.java | 4 +- .../kpelykh/docker/client/model/Ports.java | 23 ++- .../docker/client/model/SearchItem.java | 4 +- .../kpelykh/docker/client/model/Version.java | 4 +- 21 files changed, 159 insertions(+), 156 deletions(-) diff --git a/pom.xml b/pom.xml index a7390017..3de239d1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -52,6 +53,8 @@ 1.18 1.9 + 2.3.3 + 4.2.5 1.5 2.3 @@ -78,20 +81,21 @@ - com.sun.jersey - jersey-core - ${jersey.version} + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-jaxrs.version} com.sun.jersey - jersey-client + jersey-core ${jersey.version} com.sun.jersey - jersey-json + jersey-client ${jersey.version} + com.sun.jersey.contribs jersey-multipart @@ -210,93 +214,92 @@ - - - - - org.apache.maven.plugins - maven-release-plugin - ${maven-release-plugin.version} - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${jdk.source} - ${jdk.target} - ISO-8859-1 - ${jdk.debug} - ${jdk.optimize} - - - - - org.apache.maven.plugins - maven-jar-plugin - ${maven-jar-plugin.version} - - - - test-jar - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - ${skipTests} - - - - - - org.codehaus.mojo - cobertura-maven-plugin - ${cobertura-maven-plugin.version} - - - - org.apache.maven.plugins - maven-antrun-plugin - ${maven-antrun-plugin.version} - - - validate - - run - - - - ******************************************************************* - ******************************************************************* - [project.name] : ${project.name} - [project.basedir] : ${project.basedir} - [project.version] : ${project.version} - [project.artifactId] ${project.artifactId} - [project.build.directory] ${project.build.directory} - [jdk.source] : ${jdk.source} - [jdk.target] : ${jdk.target} - [jdk.debug] : ${jdk.debug} - [jdk.optimize] : ${jdk.optimize} - [source encoding]: ${project.build.sourceEncoding} - [M2_HOME] : ${env.M2_HOME} - [LocalRepository] : ${settings.localRepository} - ******************************************************************* - ******************************************************************* - - - - - - - - + + + + + org.apache.maven.plugins + maven-release-plugin + ${maven-release-plugin.version} + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${jdk.source} + ${jdk.target} + ISO-8859-1 + ${jdk.debug} + ${jdk.optimize} + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + test-jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + ${skipTests} + + + + + + org.codehaus.mojo + cobertura-maven-plugin + ${cobertura-maven-plugin.version} + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + validate + + run + + + + ******************************************************************* + ******************************************************************* + [project.name] : ${project.name} + [project.basedir] : ${project.basedir} + [project.version] : ${project.version} + [project.artifactId] ${project.artifactId} + [project.build.directory] ${project.build.directory} + [jdk.source] : ${jdk.source} + [jdk.target] : ${jdk.target} + [jdk.debug] : ${jdk.debug} + [jdk.optimize] : ${jdk.optimize} + [source encoding]: ${project.build.sourceEncoding} + [LocalRepository] : ${settings.localRepository} + ******************************************************************* + ******************************************************************* + + + + + + + + diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 1f606922..2e370b4a 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -1,5 +1,7 @@ package com.kpelykh.docker.client; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.base.Preconditions; import com.kpelykh.docker.client.model.*; import com.kpelykh.docker.client.utils.CompressArchiveUtil; @@ -9,10 +11,10 @@ import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.filter.LoggingFilter; -import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; import com.sun.jersey.core.util.MultivaluedMapImpl; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -25,14 +27,12 @@ import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -62,7 +62,7 @@ public DockerClient() { public DockerClient(String serverUrl) { restEndpointUrl = serverUrl + "/v1.11"; ClientConfig clientConfig = new DefaultClientConfig(); - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); + //clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", 4243, PlainSocketFactory.getSocketFactory())); @@ -585,8 +585,8 @@ public int waitContainer(String containerId) throws DockerException, NotFoundExc try { LOGGER.trace("POST: {}", webResource); - JSONObject jsonObject = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(JSONObject.class); - return jsonObject.getInt("StatusCode"); + ObjectNode ObjectNode = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(ObjectNode.class); + return ObjectNode.get("StatusCode").asInt(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { throw new NotFoundException(String.format("No such container %s", containerId)); @@ -595,7 +595,7 @@ public int waitContainer(String containerId) throws DockerException, NotFoundExc } else { throw new DockerException(exception); } - } catch (JSONException e) { + } catch (Exception e) { throw new DockerException(e); } } @@ -765,8 +765,8 @@ public String commit(CommitConfig commitConfig) throws DockerException, NotFound try { LOGGER.trace("POST: {}", webResource); - JSONObject jsonObject = webResource.accept("application/vnd.docker.raw-stream").post(JSONObject.class, params); - return jsonObject.getString("Id"); + ObjectNode ObjectNode = webResource.accept("application/vnd.docker.raw-stream").post(ObjectNode.class, params); + return ObjectNode.get("Id").asText(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer())); @@ -775,7 +775,7 @@ public String commit(CommitConfig commitConfig) throws DockerException, NotFound } else { throw new DockerException(exception); } - } catch (JSONException e) { + } catch (Exception e) { throw new DockerException(e); } } diff --git a/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java index 3fc709f7..514e79be 100644 --- a/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/AuthConfig.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) public class AuthConfig { diff --git a/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java b/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java index c5c30de4..9a912439 100644 --- a/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java +++ b/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java @@ -18,16 +18,15 @@ */ package com.kpelykh.docker.client.model; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; -import org.codehaus.jackson.map.annotate.JsonSerialize; - - /** * @author Kevin A. Archie * diff --git a/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java index ac45ad3e..50fdab4a 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java +++ b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * diff --git a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java index 51a83d8e..4023deb7 100644 --- a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * diff --git a/src/main/java/com/kpelykh/docker/client/model/Container.java b/src/main/java/com/kpelykh/docker/client/model/Container.java index 14970c3c..3e6554cb 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Container.java +++ b/src/main/java/com/kpelykh/docker/client/model/Container.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java index 5e9dbf7d..d0865ae0 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; import java.util.Map; diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java index 43b6144d..8f60ce15 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java index 55db87e3..555842e7 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -3,8 +3,8 @@ import java.util.Map; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * diff --git a/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java index 7fea11fc..696778a2 100755 --- a/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * Configuration object for copy command. diff --git a/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java index 3968efc1..5421bc44 100644 --- a/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java +++ b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * Created by ben on 12/12/13. diff --git a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java index ec6a043e..dc7d4258 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; diff --git a/src/main/java/com/kpelykh/docker/client/model/Image.java b/src/main/java/com/kpelykh/docker/client/model/Image.java index a6a1a18f..cfc578ce 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Image.java +++ b/src/main/java/com/kpelykh/docker/client/model/Image.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java index 26d83400..21545a2d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * Parse reponses from /images/create diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java index 187cf5c3..a7b4409e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * diff --git a/src/main/java/com/kpelykh/docker/client/model/Info.java b/src/main/java/com/kpelykh/docker/client/model/Info.java index 59e9e9ed..72f2f360 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -1,8 +1,8 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonSerialize; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; diff --git a/src/main/java/com/kpelykh/docker/client/model/Port.java b/src/main/java/com/kpelykh/docker/client/model/Port.java index 048c2ab5..538213ec 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Port.java +++ b/src/main/java/com/kpelykh/docker/client/model/Port.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @author Nicolas De Loof diff --git a/src/main/java/com/kpelykh/docker/client/model/Ports.java b/src/main/java/com/kpelykh/docker/client/model/Ports.java index d9fdab60..fc590289 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Ports.java +++ b/src/main/java/com/kpelykh/docker/client/model/Ports.java @@ -1,13 +1,14 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.*; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.codehaus.jackson.node.NullNode; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.node.NullNode; import java.io.IOException; import java.util.HashMap; @@ -93,12 +94,12 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali Ports out = new Ports(); ObjectCodec oc = jsonParser.getCodec(); JsonNode node = oc.readTree(jsonParser); - for (Iterator> it = node.getFields(); it.hasNext();) { + for (Iterator> it = node.fields(); it.hasNext();) { Map.Entry field = it.next(); if (!field.getValue().equals(NullNode.getInstance())) { - String hostIp = field.getValue().get(0).get("HostIp").getTextValue(); - String hostPort = field.getValue().get(0).get("HostPort").getTextValue(); + String hostIp = field.getValue().get(0).get("HostIp").textValue(); + String hostPort = field.getValue().get(0).get("HostPort").textValue(); out.addPort(Port.makePort(field.getKey(), hostIp, hostPort)); } } diff --git a/src/main/java/com/kpelykh/docker/client/model/SearchItem.java b/src/main/java/com/kpelykh/docker/client/model/SearchItem.java index 8478a321..d7f6eb4f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/SearchItem.java +++ b/src/main/java/com/kpelykh/docker/client/model/SearchItem.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * diff --git a/src/main/java/com/kpelykh/docker/client/model/Version.java b/src/main/java/com/kpelykh/docker/client/model/Version.java index d8d27b39..a427aafb 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -1,7 +1,7 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; /** * From 00ff6ec25af073b30377cb1a860d45f228de3a2e Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Sun, 18 May 2014 12:49:16 +0200 Subject: [PATCH 27/34] Issue #51: Building an image - ADD for remote file URL fails --- .../kpelykh/docker/client/DockerClient.java | 46 +++++++++++++------ .../docker/client/test/DockerClientTest.java | 20 ++++---- src/test/resources/testAddUrl/Dockerfile | 10 ++++ src/test/resources/testAddUrl/testrun.sh | 4 ++ 4 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 src/test/resources/testAddUrl/Dockerfile create mode 100755 src/test/resources/testAddUrl/testrun.sh diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 1f606922..44f7c64e 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -13,6 +13,7 @@ import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; import com.sun.jersey.core.util.MultivaluedMapImpl; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -33,10 +34,13 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -788,6 +792,16 @@ public ClientResponse build(File dockerFolder) throws DockerException { public ClientResponse build(File dockerFolder, String tag) throws DockerException { return this.build(dockerFolder, tag, false); } + + private static boolean isFileResource(String resource) { + URI uri; + try { + uri = new URI(resource); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + return uri.getScheme() == null || "file".equals(uri.getScheme()); + } public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException { Preconditions.checkNotNull(dockerFolder, "Folder is null"); @@ -826,19 +840,25 @@ public ClientResponse build(File dockerFolder, String tag, boolean noCache) thro throw new DockerException(String.format("Wrong format on line [%s]", cmd)); } - File src = new File(addArgs[1]); - if (!src.isAbsolute()) { - src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); - } - - if (!src.exists()) { - throw new DockerException(String.format("Source file %s doesn't exist", src)); - } - if (src.isDirectory()) { - filesToAdd.addAll(FileUtils.listFiles(src, null, true)); - } else { - filesToAdd.add(src); - } + String resource = addArgs[1]; + + if(isFileResource(resource)) { + File src = new File(resource); + if (!src.isAbsolute()) { + src = new File(dockerFolder, resource).getCanonicalFile(); + } else { + throw new DockerException(String.format("Source file %s must be relative to %s", src, dockerFolder)); + } + + if (!src.exists()) { + throw new DockerException(String.format("Source file %s doesn't exist", src)); + } + if (src.isDirectory()) { + filesToAdd.addAll(FileUtils.listFiles(src, null, true)); + } else { + filesToAdd.add(src); + } + } } } diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index 89e83a88..2267e766 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -619,18 +619,18 @@ public void testNginxDockerfileBuilder() throws DockerException, } @Test - public void testDockerBuilderAddFile() throws DockerException, IOException { + public void testDockerBuilderAddUrl() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("testAddFile").getFile()); - dockerfileBuild(baseDir, "Successfully executed testrun.sh"); + .getResource("testAddUrl").getFile()); + dockerfileBuild(baseDir, "docker.io"); } - @Test - public void testDockerBuilderAddFileInSubfolder() throws DockerException, IOException { - File baseDir = new File(Thread.currentThread().getContextClassLoader() - .getResource("testAddFileInSubfolder").getFile()); - dockerfileBuild(baseDir, "Successfully executed testrun.sh"); - } + @Test + public void testDockerBuilderAddFileInSubfolder() throws DockerException, IOException { + File baseDir = new File(Thread.currentThread().getContextClassLoader() + .getResource("testAddFileInSubfolder").getFile()); + dockerfileBuild(baseDir, "Successfully executed testrun.sh"); + } @Test public void testDockerBuilderAddFolder() throws DockerException, @@ -785,7 +785,7 @@ private String dockerfileBuild(File baseDir, String expectedText) ClientResponse logResponse = dockerClient.logContainer(container .getId()); - assertThat(logResponseStream(logResponse), endsWith(expectedText)); + assertThat(logResponseStream(logResponse), containsString(expectedText)); return container.getId(); } diff --git a/src/test/resources/testAddUrl/Dockerfile b/src/test/resources/testAddUrl/Dockerfile new file mode 100644 index 00000000..1d76926c --- /dev/null +++ b/src/test/resources/testAddUrl/Dockerfile @@ -0,0 +1,10 @@ +FROM ubuntu + +# Copy testrun.sh files into the container + +ADD http://www.docker.io /tmp/docker_home.html +ADD ./testrun.sh /tmp/ + +RUN cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh + +CMD ["testrun.sh"] \ No newline at end of file diff --git a/src/test/resources/testAddUrl/testrun.sh b/src/test/resources/testAddUrl/testrun.sh new file mode 100755 index 00000000..8eb4630b --- /dev/null +++ b/src/test/resources/testAddUrl/testrun.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cat /tmp/docker_home.html + From 3fcf3d7267994fb2e76bc86da16939ee8543c2cb Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 18 May 2014 19:08:49 +0100 Subject: [PATCH 28/34] added support for a single centralized configuration --- .../com/kpelykh/docker/client/Config.java | 57 +++++++++++++++++++ .../kpelykh/docker/client/DockerClient.java | 55 ++++++++++++------ .../docker/client/model/ContainerConfig.java | 2 +- src/main/resources/docker.io.properties | 2 + .../client/test/AbstractDockerClientTest.java | 33 +++-------- .../client/test/DockerClientAuthTest.java | 26 ++++----- .../docker/client/test/DockerPushTest.java | 52 +++++++---------- 7 files changed, 136 insertions(+), 91 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/Config.java create mode 100644 src/main/resources/docker.io.properties diff --git a/src/main/java/com/kpelykh/docker/client/Config.java b/src/main/java/com/kpelykh/docker/client/Config.java new file mode 100644 index 00000000..e5ae6115 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/Config.java @@ -0,0 +1,57 @@ +package com.kpelykh.docker.client; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.Properties; + +class Config { + URI url; + String version, username, password, email; + + private Config() { + } + + static Config createConfig() throws DockerException { + final Properties p = new Properties(); + + try { + p.load(DockerClient.class.getResourceAsStream("/docker.io.properties")); + } catch (IOException e) { + throw new DockerException(e); + } + + for (String s : new String[]{"url", "version", "username", "password", "email"}) { + final String key = "docker.io." + s; + if (System.getProperties().keySet().contains(key)) { + p.setProperty(key, System.getProperty(key)); + } + } + + final File file = new File(System.getProperty("user.name"), ".docker.io.properties"); + System.out.println(file); + if (file.isFile()) { + try { + final FileInputStream in = new FileInputStream(file); + try { + p.load(in); + } finally { + in.close(); + } + } catch (IOException e) { + throw new DockerException(e); + } + } + + final Config c = new Config(); + + c.url = URI.create(p.getProperty("docker.io.url")); + c.version = p.getProperty("docker.io.version"); + c.username = p.getProperty("docker.io.username"); + c.password = p.getProperty("docker.io.password"); + c.email = p.getProperty("docker.io.email"); + + return c; + } +} diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 1f606922..5f723b90 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -50,22 +51,31 @@ public class DockerClient { private static final Logger LOGGER = LoggerFactory.getLogger(DockerClient.class); - private static DockerClient instance; - private Client client; + private Client client; private String restEndpointUrl; private AuthConfig authConfig; - public DockerClient() { - this("http://localhost:4243"); + public DockerClient() throws DockerException { + this(Config.createConfig()); } - public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.11"; + public DockerClient(String serverUrl) throws DockerException { + this(configWithServerUrl(serverUrl)); + } + + private static Config configWithServerUrl(String serverUrl) throws DockerException { + final Config c = Config.createConfig(); + c.url = URI.create(serverUrl); + return c; + } + + private DockerClient(Config config) { + restEndpointUrl = config.url + "/v" + config.version; ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("http", 4243, PlainSocketFactory.getSocketFactory())); + schemeRegistry.register(new Scheme("http", config.url.getPort(), PlainSocketFactory.getSocketFactory())); schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory())); PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); @@ -105,7 +115,6 @@ public void setCredentials(String username, String password, String email) { * Authenticate with the server, useful for checking authentication. */ public void auth() throws DockerException { - checkAuthConfig(); try { client.resource(restEndpointUrl + "/auth") .header("Content-Type", MediaType.APPLICATION_JSON) @@ -124,18 +133,28 @@ private String registryAuth() throws DockerException { } } - private AuthConfig authConfig() throws DockerException { - checkAuthConfig(); - return authConfig; - } + public AuthConfig authConfig() throws DockerException { + return authConfig != null + ? authConfig + : authConfigFromProperties(); + } - private void checkAuthConfig() throws DockerException { - if (authConfig == null) { - throw new DockerException("authentication credentials required"); - } - } + private static AuthConfig authConfigFromProperties() throws DockerException { + final AuthConfig a = new AuthConfig(); - /** + a.setUsername(Config.createConfig().username); + a.setPassword(Config.createConfig().password); + a.setEmail(Config.createConfig().email); + + if (a.getUsername() == null) {throw new IllegalStateException("username is null");} + if (a.getPassword() == null) {throw new IllegalStateException("password is null");} + if (a.getEmail() == null) {throw new IllegalStateException("email is null");} + + return a; + } + + + /** * * MISC API * * */ diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java index 5e9dbf7d..413020d2 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -285,7 +285,7 @@ public String toString() { ", privileged=" + privileged + ", workingDir='" + workingDir + '\'' + ", domainName='" + domainName + '\'' + - ", onBuild='" + onBuild + '\'' + + ", onBuild='" + Arrays.toString(onBuild) + '\'' + '}'; } } diff --git a/src/main/resources/docker.io.properties b/src/main/resources/docker.io.properties new file mode 100644 index 00000000..0ce162bd --- /dev/null +++ b/src/main/resources/docker.io.properties @@ -0,0 +1,2 @@ +docker.io.url=http://localhost:4243 +docker.io.version=1.11 \ No newline at end of file diff --git a/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java index eb9bcf73..be878f78 100644 --- a/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java @@ -1,18 +1,17 @@ package com.kpelykh.docker.client.test; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - +import com.kpelykh.docker.client.DockerClient; +import com.kpelykh.docker.client.DockerException; +import com.sun.jersey.api.client.ClientResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.ITestResult; -import com.kpelykh.docker.client.DockerClient; -import com.kpelykh.docker.client.DockerException; -import com.sun.jersey.api.client.ClientResponse; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; public abstract class AbstractDockerClientTest extends Assert { @@ -81,23 +80,5 @@ protected String logResponseStream(ClientResponse response) throws IOException { LOG.info("Container log: {}", responseString); return responseString; } - - private String getProperty(String name) { - String property = System.getProperty(name); - if(property == null || property.isEmpty()) throw new RuntimeException("Need to configure '" + name + "' property to run the test. Use command line option -D"+ name +"=... to do so."); - return property; - } - - protected String getUsername() { - return getProperty("docker.io.username"); - } - - protected String getPassword() { - return getProperty("docker.io.password"); - } - - protected String getEmail() { - return getProperty("docker.io.email"); - } } diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java index 6fe6e999..30a33a0c 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientAuthTest.java @@ -1,20 +1,14 @@ package com.kpelykh.docker.client.test; -import static org.hamcrest.MatcherAssert.assertThat; - -import java.lang.reflect.Method; -import java.util.ArrayList; - +import com.kpelykh.docker.client.DockerException; +import com.sun.jersey.api.client.UniformInterfaceException; import org.hamcrest.Matchers; import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; +import org.testng.annotations.*; -import com.kpelykh.docker.client.DockerException; -import com.sun.jersey.api.client.UniformInterfaceException; +import java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; public class DockerClientAuthTest extends AbstractDockerClientTest { @@ -36,21 +30,21 @@ public void beforeMethod(Method method) { public void afterMethod(ITestResult result) { super.afterMethod(result); } - + @Test public void testAuth() throws Exception { - dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); dockerClient.auth(); } @Test public void testAuthInvalid() throws Exception { - dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); + System.setProperty("docker.io.password", "garbage"); try { dockerClient.auth(); + fail(); } catch (DockerException e) { assertThat(e.getCause(), Matchers.instanceOf(UniformInterfaceException.class)); - assertEquals(401, ((UniformInterfaceException) e.getCause()).getResponse().getStatus()); + assertEquals(((UniformInterfaceException) e.getCause()).getResponse().getStatus(), 401); } } } diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java index b5709f96..7e6d88a9 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerPushTest.java @@ -1,27 +1,20 @@ package com.kpelykh.docker.client.test; -import static com.kpelykh.docker.client.DockerClient.asString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; - -import java.lang.reflect.Method; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - import com.kpelykh.docker.client.DockerException; import com.kpelykh.docker.client.model.CommitConfig; import com.kpelykh.docker.client.model.ContainerConfig; import com.kpelykh.docker.client.model.ContainerCreateResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.ITestResult; +import org.testng.annotations.*; + +import java.lang.reflect.Method; + +import static com.kpelykh.docker.client.DockerClient.asString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; // delete here : https://index.docker.io/u/alexec/busybox/delete/ public class DockerPushTest extends AbstractDockerClientTest { @@ -29,9 +22,12 @@ public class DockerPushTest extends AbstractDockerClientTest { public static final Logger LOG = LoggerFactory .getLogger(DockerPushTest.class); + String username; + @BeforeTest public void beforeTest() throws DockerException { super.beforeTest(); + username = dockerClient.authConfig().getUsername(); } @AfterTest public void afterTest() { @@ -47,10 +43,10 @@ public void beforeMethod(Method method) { public void afterMethod(ITestResult result) { super.afterMethod(result); } - + @Test public void testPushLatest() throws Exception { - setUpCredentials(); + ContainerConfig containerConfig = new ContainerConfig(); containerConfig.setImage("busybox"); @@ -67,26 +63,22 @@ public void testPushLatest() throws Exception { LOG.info("Commiting container: {}", container.toString()); CommitConfig commitConfig = new CommitConfig(container.getId()); - commitConfig.setRepo(getUsername() + "/busybox"); - - String imageId = dockerClient - .commit(commitConfig); + + commitConfig.setRepo(username + "/busybox"); - logResponseStream(dockerClient.push(getUsername() + "/busybox")); + String imageId = dockerClient.commit(commitConfig); + + logResponseStream(dockerClient.push(username + "/busybox")); dockerClient.removeImage(imageId); - assertThat(asString(dockerClient.pull(getUsername() + "/busybox")), not(containsString("404"))); + assertThat(asString(dockerClient.pull(username + "/busybox")), not(containsString("404"))); } @Test public void testNotExistentImage() throws Exception { - setUpCredentials(); - assertThat(logResponseStream(dockerClient.push(getUsername() + "/xxx")), containsString("error")); - } - private void setUpCredentials() { - dockerClient.setCredentials(getUsername(), getPassword(), getEmail()); + assertThat(logResponseStream(dockerClient.push(username + "/xxx")), containsString("error")); } From 9cf0799d1aa8c5de44aa7fe8b5336f5b494a9e64 Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 18 May 2014 21:52:26 +0100 Subject: [PATCH 29/34] README update --- README.md | 41 +++++++++++++++++-- .../com/kpelykh/docker/client/Config.java | 2 +- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 76075d2f..c3e292de 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ listening on TCP port. To allow Docker server to use TCP add the following line More details setting up docket server can be found in official documentation: http://docs.docker.io/en/latest/use/basics/ Now make sure that docker is up: - + $ docker -H tcp://127.0.0.1:4243 version Client version: 0.8.1 @@ -63,12 +63,12 @@ Run build with tests: Info info = dockerClient.info(); System.out.print(info); - + ###### Search Docker repository: List dockerSearch = dockerClient.search("busybox"); System.out.println("Search returned" + dockerSearch.toString()); - + ###### Create new Docker container, wait for its start and stop it: ContainerConfig containerConfig = new ContainerConfig(); @@ -81,7 +81,7 @@ Run build with tests: dockerClient.waitContainer(container.id); dockerClient.stopContainer(container.id); - + ##### Support for UNIX sockets: @@ -114,3 +114,36 @@ user dockerClient.build(baseDir), where baseDir is a path to folder containing D For additional examples, please look at [DockerClientTest.java](https://github.com/kpelykh/docker-java/blob/master/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java "DockerClientTest.java") +## Configuration + +There are a couple of configuration items, all of which have sensible defaults: + +* `url` The Docker URL, e.g. `http://localhost:4243`. +* `version` The API version, e.g. `1.11`. +* `username` Your repository username (required to push containers). +* `password` Your repository password. +* `email` Your repository email. + +There are three ways to configure, in descending order of precedence: + +##### Programatic: +In your application, e.g. + + DockerClient docker = new DockerClient("http://localhost:4243"); + docker.setCredentials("dockeruser", "ilovedocker", "dockeruser@github.com");` + +##### System Properties: +E.g. + + java -Ddocker.io.username=kpelykh pkg.Main + +##### File System +In `$HOME/.docker.io.properties`, e.g.: + + docker.io.username=dockeruser + +##### Class Path +In the class path at `/docker.io.properties`, e.g.: + + docker.io.url=http://localhost:4243 + docker.io.version=1.11 diff --git a/src/main/java/com/kpelykh/docker/client/Config.java b/src/main/java/com/kpelykh/docker/client/Config.java index e5ae6115..aa029a22 100644 --- a/src/main/java/com/kpelykh/docker/client/Config.java +++ b/src/main/java/com/kpelykh/docker/client/Config.java @@ -17,7 +17,7 @@ static Config createConfig() throws DockerException { final Properties p = new Properties(); try { - p.load(DockerClient.class.getResourceAsStream("/docker.io.properties")); + p.load(Config.class.getResourceAsStream("/docker.io.properties")); } catch (IOException e) { throw new DockerException(e); } From 62be275033d70340dee7ff0a01ea600df56c6cdf Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 22 May 2014 22:02:23 +0200 Subject: [PATCH 30/34] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c3e292de..24cfc9ad 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,9 @@ Developer forum for [docker-java](https://groups.google.com/forum/?hl=de#!forum/ * Maven 3.0.5 * Docker daemon running -Maven will run tests during build process. Tests are using localhost instance of Docker, make sure that -you have Docker running for tests to work or just turn off tests. - -If you don't have Docker running locally, you can skip tests with -DskipTests flag set to true: - - $ mvn clean install -DskipTests=true +Maven may run tests during build process but tests are disabled by default. The tests are using a localhost instance of Docker, make sure that you have Docker running for tests to work. To run the tests you have to provide your https://www.docker.io/account/login/ information: + $ mvn clean install -DskipTests=false -Ddocker.io.username=... -Ddocker.io.password=... -Ddocker.io.email=... By default Docker server is using UNIX sockets for communication with the Docker client, however docker-java client uses TCP/IP to connect to the Docker server, so you will need to make sure that your Docker server is From 620e45605dae20333ca5d5dc8483cd38005f6369 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 23 May 2014 22:15:55 +0200 Subject: [PATCH 31/34] Various fixes --- .../com/kpelykh/docker/client/Config.java | 18 +++++------ .../kpelykh/docker/client/DockerClient.java | 2 +- .../model/ContainerInspectResponse.java | 10 +++---- .../client/model/ImageInspectResponse.java | 6 ++-- .../client/test/AbstractDockerClientTest.java | 4 ++- .../docker/client/test/DockerClientTest.java | 30 +++++++++++++++---- 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/Config.java b/src/main/java/com/kpelykh/docker/client/Config.java index aa029a22..f6e59d76 100644 --- a/src/main/java/com/kpelykh/docker/client/Config.java +++ b/src/main/java/com/kpelykh/docker/client/Config.java @@ -22,16 +22,9 @@ static Config createConfig() throws DockerException { throw new DockerException(e); } - for (String s : new String[]{"url", "version", "username", "password", "email"}) { - final String key = "docker.io." + s; - if (System.getProperties().keySet().contains(key)) { - p.setProperty(key, System.getProperty(key)); - } - } + final File file = new File(System.getProperty("user.home"), ".docker.io.properties"); - final File file = new File(System.getProperty("user.name"), ".docker.io.properties"); - System.out.println(file); - if (file.isFile()) { + if (file.isFile()) { try { final FileInputStream in = new FileInputStream(file); try { @@ -44,6 +37,13 @@ static Config createConfig() throws DockerException { } } + for (String s : new String[]{"url", "version", "username", "password", "email"}) { + final String key = "docker.io." + s; + if (System.getProperties().keySet().contains(key)) { + p.setProperty(key, System.getProperty(key)); + } + } + final Config c = new Config(); c.url = URI.create(p.getProperty("docker.io.url")); diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index d1070f80..7bba645f 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -108,7 +108,7 @@ public void setCredentials(String username, String password, String email) { } authConfig = new AuthConfig(); authConfig.setUsername(username); - authConfig.setPassword(password); + authConfig.setPassword(password); authConfig.setEmail(email); } diff --git a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java index 555842e7..d686f9eb 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -33,7 +33,7 @@ public class ContainerInspectResponse { private ContainerState state; @JsonProperty("Image") - private String image; + private String imageId; @JsonProperty("NetworkSettings") private NetworkSettings networkSettings; @@ -119,12 +119,12 @@ public void setState(ContainerState state) { this.state = state; } - public String getImage() { - return image; + public String getImageId() { + return imageId; } - public void setImage(String image) { - this.image = image; + public void setImageId(String image) { + this.imageId = image; } public NetworkSettings getNetworkSettings() { diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java index a7b4409e..3514670c 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java @@ -22,7 +22,7 @@ public class ImageInspectResponse { @JsonProperty("container_config") private ContainerConfig containerConfig; - @JsonProperty("Size") private int size; + @JsonProperty("Size") private long size; @JsonProperty("docker_version") private String dockerVersion; @@ -76,11 +76,11 @@ public void setContainerConfig(ContainerConfig containerConfig) { this.containerConfig = containerConfig; } - public int getSize() { + public long getSize() { return size; } - public void setSize(int size) { + public void setSize(long size) { this.size = size; } diff --git a/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java index 8904702e..d8313ca4 100644 --- a/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/AbstractDockerClientTest.java @@ -30,9 +30,11 @@ public void beforeTest() throws DockerException { LOG.info("Connecting to Docker server at " + url); dockerClient = new DockerClient(url); - LOG.info("Creating image 'busybox'"); + LOG.info("Pulling image 'busybox'"); // need to block until image is pulled completely logResponseStream(dockerClient.pull("busybox")); + + assertNotNull(dockerClient); LOG.info("======================= END OF BEFORETEST =======================\n\n"); diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index 2267e766..ccf09ea9 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -151,6 +151,14 @@ public void testImages() throws DockerException { @Test public void testListContainers() throws DockerException { + + String testImage = "hackmann/empty"; + + LOG.info("Pulling image 'hackmann/empty'"); + // need to block until image is pulled completely + logResponseStream(dockerClient.pull(testImage)); + tmpImgs.add(testImage); + List containers = dockerClient.listContainers(true); assertThat(containers, notNullValue()); LOG.info("Container List: {}", containers); @@ -158,18 +166,30 @@ public void testListContainers() throws DockerException { int size = containers.size(); ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); + containerConfig.setImage(testImage); containerConfig.setCmd(new String[] { "echo" }); ContainerCreateResponse container1 = dockerClient .createContainer(containerConfig); + assertThat(container1.getId(), not(isEmptyString())); + + ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container1.getId()); + + assertThat(containerInspectResponse.getConfig().getImage(), is(equalTo(testImage))); + + dockerClient.startContainer(container1.getId()); tmpContainers.add(container1.getId()); LOG.info("container id: " + container1.getId()); - List containers2 = dockerClient.listContainers(true); + List containers2 = dockerClient.listContainers(true); + + for(Container container: containers2) { + LOG.info("listContainer: id=" + container.getId() +" image=" + container.getImage()); + } + assertThat(size + 1, is(equalTo(containers2.size()))); Matcher matcher = hasItem(hasField("id", startsWith(container1.getId()))); assertThat(containers2, matcher); @@ -179,12 +199,12 @@ public void testListContainers() throws DockerException { assertThat(filteredContainers.size(), is(equalTo(1))); for(Container container: filteredContainers) { - LOG.info("container: " + container); + LOG.info("filteredContainer: " + container.getImage()); } Container container2 = filteredContainers.get(0); assertThat(container2.getCommand(), not(isEmptyString())); - assertThat(container2.getImage(), equalTo("busybox:latest")); + assertThat(container2.getImage(), equalTo(testImage + ":latest")); } /* @@ -232,7 +252,7 @@ public void testStartContainer() throws DockerException { assertThat(containerInspectResponse.getId(), startsWith(container.getId())); - assertThat(containerInspectResponse.getImage(), not(isEmptyString())); + assertThat(containerInspectResponse.getImageId(), not(isEmptyString())); assertThat(containerInspectResponse.getState(), is(notNullValue())); assertThat(containerInspectResponse.getState().running, is(true)); From 9aa7c50217fc85152cf20bc515ef1a2a19856eef Mon Sep 17 00:00:00 2001 From: Vojtech Juranek Date: Sun, 8 Jun 2014 23:10:39 +0200 Subject: [PATCH 32/34] Add ping method --- .../com/kpelykh/docker/client/DockerClient.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 7bba645f..c9719c6b 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -190,6 +190,19 @@ public Version version() throws DockerException { } } } + + + public int ping() throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/_ping"); + + try { + LOGGER.trace("GET: {}", webResource); + ClientResponse resp = webResource.get(ClientResponse.class); + return resp.getStatus(); + } catch (UniformInterfaceException exception) { + throw new DockerException(exception); + } + } /** From 1a997a0b783d2f4363c78bfdb13c7be5d97ac7e5 Mon Sep 17 00:00:00 2001 From: Yoann Dubreuil Date: Tue, 10 Jun 2014 16:19:01 +0200 Subject: [PATCH 33/34] add tag method on image --- .../kpelykh/docker/client/DockerClient.java | 30 +++++++++++++++++++ .../docker/client/test/DockerClientTest.java | 12 ++++++++ 2 files changed, 42 insertions(+) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index c9719c6b..101d7209 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -293,6 +293,36 @@ private String name(String name) { return name.contains("/") ? name : authConfig.getUsername(); } + /** + * Tag an image into a repository + * + * @param image the local image to tag (either a name or an id) + * @param repository the repository to tag in + * @param tag any tag for this image + * @param force (not documented) + * @return the HTTP status code (201 for success) + */ + public int tag(String image, String repository, String tag, boolean force) throws DockerException { + Preconditions.checkNotNull(image, "image was not specified"); + Preconditions.checkNotNull(repository, "repository was not specified"); + Preconditions.checkNotNull(tag, " tag was not provided"); + + MultivaluedMap params = new MultivaluedMapImpl(); + params.add("repo", repository); + params.add("tag", tag); + params.add("force", String.valueOf(force)); + + WebResource webResource = client.resource(restEndpointUrl + "/images/" + image + "/tag").queryParams(params); + + try { + LOGGER.trace("POST: {}", webResource); + ClientResponse resp = webResource.post(ClientResponse.class); + return resp.getStatus(); + } catch (UniformInterfaceException exception) { + throw new DockerException(exception); + } + } + /** * Create an image by importing the given stream of a tar file. * diff --git a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java index ccf09ea9..f6af3823 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -25,10 +25,12 @@ import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.List; +import java.util.Random; import org.apache.commons.io.IOUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.RandomUtils; import org.hamcrest.Matcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -569,6 +571,16 @@ public void testRemoveImage() throws DockerException, InterruptedException { assertThat(containers, matcher); } + @Test + public void testTagImage() throws DockerException, InterruptedException { + String tag = String.valueOf(RandomUtils.nextInt(Integer.MAX_VALUE)); + + Integer result = dockerClient.tag("busybox:latest", "docker-java/busybox", tag, false); + assertThat(result, equalTo(Integer.valueOf(201))); + + dockerClient.removeImage("docker-java/busybox:" + tag); + } + /* * * ################ ## MISC TESTS ## ################ From 26b4069bb1985a8c293a016aaf9b56979771d75b Mon Sep 17 00:00:00 2001 From: marcuslinke Date: Thu, 12 Jun 2014 20:27:06 +0200 Subject: [PATCH 34/34] Update README.md --- README.md | 146 +----------------------------------------------------- 1 file changed, 2 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index 24cfc9ad..a51128f7 100644 --- a/README.md +++ b/README.md @@ -1,145 +1,3 @@ -# docker-java +This project has moved to https://github.com/docker-java/docker-java +-------------------------------------------------------------------- -Java API client for [Docker](http://docs.docker.io/ "Docker") - -Supports a subset of the Docker Client API v1.11, Docker Server version 0.11 - -Developer forum for [docker-java](https://groups.google.com/forum/?hl=de#!forum/docker-java-dev "docker-java") - -## Build with Maven - -###### Prerequisites: - -* Java 1.6+ -* Maven 3.0.5 -* Docker daemon running - -Maven may run tests during build process but tests are disabled by default. The tests are using a localhost instance of Docker, make sure that you have Docker running for tests to work. To run the tests you have to provide your https://www.docker.io/account/login/ information: - - $ mvn clean install -DskipTests=false -Ddocker.io.username=... -Ddocker.io.password=... -Ddocker.io.email=... - -By default Docker server is using UNIX sockets for communication with the Docker client, however docker-java -client uses TCP/IP to connect to the Docker server, so you will need to make sure that your Docker server is -listening on TCP port. To allow Docker server to use TCP add the following line to /etc/default/docker - - DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock" - -More details setting up docket server can be found in official documentation: http://docs.docker.io/en/latest/use/basics/ - -Now make sure that docker is up: - - $ docker -H tcp://127.0.0.1:4243 version - - Client version: 0.8.1 - Go version (client): go1.2 - Git commit (client): a1598d1 - Server version: 0.8.1 - Git commit (server): a1598d1 - Go version (server): go1.2 - Last stable version: 0.8.1 - -Run build with tests: - - $ mvn clean install - -## Docker-Java maven dependency: - - - com.kpelykh - docker-java - 0.8.1 - - - -## Example code snippets: - - DockerClient dockerClient = new DockerClient("http://localhost:4243"); - -###### Get Docker info: - - Info info = dockerClient.info(); - System.out.print(info); - -###### Search Docker repository: - - List dockerSearch = dockerClient.search("busybox"); - System.out.println("Search returned" + dockerSearch.toString()); - -###### Create new Docker container, wait for its start and stop it: - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"touch", "/test"}); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - - dockerClient.startContainer(container.id); - - dockerClient.waitContainer(container.id); - - dockerClient.stopContainer(container.id); - - -##### Support for UNIX sockets: - - Support for UNIX socket should appear in docker-java pretty soon. I'm working on its integration. - -##### Docker Builder: - -To use Docker Builder, as described on page http://docs.docker.io/en/latest/use/builder/, -user dockerClient.build(baseDir), where baseDir is a path to folder containing Dockerfile. - - - File baseDir = new File("~/kpelykh/docker/netcat"); - - ClientResponse response = dockerClient.build(baseDir); - - StringWriter logwriter = new StringWriter(); - - try { - LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8"); - while (itr.hasNext()) { - String line = itr.next(); - logwriter.write(line); - LOG.info(line); - } - } finally { - IOUtils.closeQuietly(response.getEntityInputStream()); - } - - - -For additional examples, please look at [DockerClientTest.java](https://github.com/kpelykh/docker-java/blob/master/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java "DockerClientTest.java") - -## Configuration - -There are a couple of configuration items, all of which have sensible defaults: - -* `url` The Docker URL, e.g. `http://localhost:4243`. -* `version` The API version, e.g. `1.11`. -* `username` Your repository username (required to push containers). -* `password` Your repository password. -* `email` Your repository email. - -There are three ways to configure, in descending order of precedence: - -##### Programatic: -In your application, e.g. - - DockerClient docker = new DockerClient("http://localhost:4243"); - docker.setCredentials("dockeruser", "ilovedocker", "dockeruser@github.com");` - -##### System Properties: -E.g. - - java -Ddocker.io.username=kpelykh pkg.Main - -##### File System -In `$HOME/.docker.io.properties`, e.g.: - - docker.io.username=dockeruser - -##### Class Path -In the class path at `/docker.io.properties`, e.g.: - - docker.io.url=http://localhost:4243 - docker.io.version=1.11