From a19aa436da8b1bfe937d68ea08b9f18d99702ac4 Mon Sep 17 00:00:00 2001 From: Frank Scholten Date: Fri, 20 Dec 2013 16:13:14 +0100 Subject: [PATCH 01/72] Added experiment with jnr-unixsocket. --- pom.xml | 7 +++ .../kpelykh/docker/client/DockerClient.java | 6 ++- .../docker/client/UnixSocketClient.java | 11 ++++ .../client/UnixSocketClientHandler.java | 52 +++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketClient.java create mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java diff --git a/pom.xml b/pom.xml index c48199e8..392bc3b2 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,7 @@ 2.6 1.7.5 1.3.9 + 0.3 1.0.1 @@ -123,6 +124,12 @@ ${commons-io.version} + + com.github.jnr + jnr-unixsocket + ${jnr.unixsocket.version} + + org.slf4j slf4j-api diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index e155f53b..dbb553c4 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -15,6 +15,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.client.HttpClient; +import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; @@ -60,8 +61,9 @@ public DockerClient(String serverUrl) { // Increase default max connection per route cm.setDefaultMaxPerRoute(1000); - HttpClient httpClient = new DefaultHttpClient(cm); - client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); + // HttpClient httpClient = new DefaultHttpClient(cm); + // client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); + client = new UnixSocketClient(); client.addFilter(new JsonClientFilter()); //client.addFilter(new LoggingFilter()); diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java new file mode 100644 index 00000000..12bdf5e4 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java @@ -0,0 +1,11 @@ +package com.kpelykh.docker.client; + +import com.sun.jersey.api.client.Client; + + +public class UnixSocketClient extends Client { + + public UnixSocketClient() { + super(new UnixSocketClientHandler()); + } +} diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java new file mode 100644 index 00000000..4962a362 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java @@ -0,0 +1,52 @@ +package com.kpelykh.docker.client; + +import com.sun.jersey.api.client.ClientHandler; +import com.sun.jersey.api.client.ClientHandlerException; +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import jnr.unixsocket.UnixSocketAddress; +import jnr.unixsocket.UnixSocketChannel; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.nio.CharBuffer; +import java.nio.channels.Channels; + +public class UnixSocketClientHandler implements ClientHandler { + + @Override + public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { + System.out.println("UnixSocketClientHandler.handle " + cr); + + File path = new File("/var/run/docker.sock"); + + String data = "GET /images/json?all=0 HTTP/1.1\n\n"; + + UnixSocketAddress address = new UnixSocketAddress(path); + UnixSocketChannel channel = null; + try { + channel = UnixSocketChannel.open(address); + } catch (IOException e) { + e.printStackTrace(); + } + System.out.println("connected to " + channel.getRemoteSocketAddress()); + PrintWriter w = new PrintWriter(Channels.newOutputStream(channel)); + w.print(data); + w.flush(); + + InputStreamReader r = new InputStreamReader(Channels.newInputStream(channel)); + + CharBuffer result = CharBuffer.allocate(1024); + try { + r.read(result); + } catch (IOException e) { + e.printStackTrace(); + } + result.flip(); + System.out.println("read from server: " + result.toString()); + + return null; + } +} From 02ec81c63ca4ca08d5fb281286ef9e052ff0ef94 Mon Sep 17 00:00:00 2001 From: Frank Scholten Date: Mon, 23 Dec 2013 18:04:18 +0100 Subject: [PATCH 02/72] Added input and output session buffers. Printed status, type and headers of response from socket. Added constants and helper methods from ApacheHttpClient4Handler. --- .../kpelykh/docker/client/DockerClient.java | 10 +- .../client/UnixSocketClientHandler.java | 224 +++++++++++++++--- .../client/UnixSocketSessionInputBuffer.java | 23 ++ .../client/UnixSocketSessionOutputBuffer.java | 17 ++ .../docker/client/test/DockerClientTest.java | 2 +- 5 files changed, 242 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java create mode 100644 src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index dbb553c4..b16471d5 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -48,12 +48,12 @@ public class DockerClient private String restEndpointUrl; public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.3"; + restEndpointUrl = "/v1.3"; 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", 4243, PlainSocketFactory.getSocketFactory())); PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); // Increase max total connection @@ -61,11 +61,11 @@ public DockerClient(String serverUrl) { // Increase default max connection per route cm.setDefaultMaxPerRoute(1000); - // HttpClient httpClient = new DefaultHttpClient(cm); - // client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); + //HttpClient httpClient = new DefaultHttpClient(cm); + //client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); client = new UnixSocketClient(); - client.addFilter(new JsonClientFilter()); + //client.addFilter(new JsonClientFilter()); //client.addFilter(new LoggingFilter()); } diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java index 4962a362..a9fd5621 100644 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java @@ -1,52 +1,220 @@ package com.kpelykh.docker.client; -import com.sun.jersey.api.client.ClientHandler; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; +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.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.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.nio.CharBuffer; +import javax.annotation.concurrent.NotThreadSafe; +import java.io.*; +import java.net.URI; import java.nio.channels.Channels; +import java.util.ArrayList; +import java.util.List; -public class UnixSocketClientHandler implements ClientHandler { +/** + * 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 { - System.out.println("UnixSocketClientHandler.handle " + cr); + LOGGER.info("handle " + cr); + + try { + File path = new File(DOCKER_SOCKET_PATH); + UnixSocketAddress address = new UnixSocketAddress(path); + UnixSocketChannel channel = UnixSocketChannel.open(address); + OutputStream unixSocketChannelOutputStream = Channels.newOutputStream(channel); - File path = new File("/var/run/docker.sock"); + final HttpUriRequest request = getUriHttpRequest(cr); + BasicHttpParams params = new BasicHttpParams(); - String data = "GET /images/json?all=0 HTTP/1.1\n\n"; + 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(); + + ClientResponse clientResponse = new ClientResponse(response.getStatusLine().getStatusCode(), + getInBoundHeaders(response), + new HttpClientResponseInputStream(response), + getMessageBodyWorkers()); + if (!clientResponse.hasEntity()) { + clientResponse.bufferEntity(); + clientResponse.close(); + } + + System.out.println(clientResponse.getType()); + System.out.println(clientResponse.getClientResponseStatus()); + System.out.println(clientResponse.getStatus()); + System.out.println(clientResponse.getHeaders()); + + return clientResponse; - UnixSocketAddress address = new UnixSocketAddress(path); - UnixSocketChannel channel = null; - try { - channel = UnixSocketChannel.open(address); } catch (IOException e) { e.printStackTrace(); + } catch (HttpException e) { + e.printStackTrace(); } - System.out.println("connected to " + channel.getRemoteSocketAddress()); - PrintWriter w = new PrintWriter(Channels.newOutputStream(channel)); - w.print(data); - w.flush(); + 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; + } - InputStreamReader r = new InputStreamReader(Channels.newInputStream(channel)); + private HttpEntity getHttpEntity(final ClientRequest cr) { + final Object entity = cr.getEntity(); + + if (entity == null) + return null; + + final RequestEntityWriter requestEntityWriter = getRequestEntityWriter(cr); - CharBuffer result = CharBuffer.allocate(1024); try { - r.read(result); - } catch (IOException e) { - e.printStackTrace(); + 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? } - result.flip(); - System.out.println("read from server: " + result.toString()); 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 new file mode 100644 index 00000000..9c7f150c --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java @@ -0,0 +1,23 @@ +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 new file mode 100644 index 00000000..411096ff --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java @@ -0,0 +1,17 @@ +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 ca37013b..565facac 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -46,7 +46,7 @@ public class DockerClientTest extends Assert public void beforeTest() throws DockerException { LOG.info("======================= BEFORETEST ======================="); LOG.info("Connecting to Docker server at http://localhost:4243"); - dockerClient = new DockerClient("http://localhost:4243"); + dockerClient = new DockerClient("http://www.nu.nl"); LOG.info("Creating image 'busybox'"); dockerClient.pull("busybox"); From 5395edb5e8986c2e62101cad14bbc23ce61ef737 Mon Sep 17 00:00:00 2001 From: Frank Scholten Date: Tue, 24 Dec 2013 17:54:30 +0100 Subject: [PATCH 03/72] Added client config to UnixSocketClientHandler. --- .../com/kpelykh/docker/client/DockerClient.java | 11 ++++++----- .../com/kpelykh/docker/client/UnixSocketClient.java | 5 +++-- .../docker/client/UnixSocketClientHandler.java | 13 +++---------- .../docker/client/test/DockerClientTest.java | 6 +++--- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index b16471d5..296136e2 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -8,6 +8,7 @@ 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; @@ -53,7 +54,7 @@ public DockerClient(String serverUrl) { 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", 4243, PlainSocketFactory.getSocketFactory())); PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); // Increase max total connection @@ -61,12 +62,12 @@ public DockerClient(String serverUrl) { // Increase default max connection per route cm.setDefaultMaxPerRoute(1000); - //HttpClient httpClient = new DefaultHttpClient(cm); + // HttpClient httpClient = new DefaultHttpClient(cm); //client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); - client = new UnixSocketClient(); + client = new UnixSocketClient(clientConfig); - //client.addFilter(new JsonClientFilter()); - //client.addFilter(new LoggingFilter()); + client.addFilter(new JsonClientFilter()); + client.addFilter(new LoggingFilter()); } /** diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java index 12bdf5e4..75582037 100644 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java @@ -1,11 +1,12 @@ 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() { - super(new UnixSocketClientHandler()); + 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 index a9fd5621..3b1ef752 100644 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java @@ -42,8 +42,6 @@ public class UnixSocketClientHandler extends RequestWriter implements ClientHand @Override public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { - LOGGER.info("handle " + cr); - try { File path = new File(DOCKER_SOCKET_PATH); UnixSocketAddress address = new UnixSocketAddress(path); @@ -63,20 +61,15 @@ public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { 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()); - if (!clientResponse.hasEntity()) { - clientResponse.bufferEntity(); - clientResponse.close(); - } - System.out.println(clientResponse.getType()); - System.out.println(clientResponse.getClientResponseStatus()); - System.out.println(clientResponse.getStatus()); - System.out.println(clientResponse.getHeaders()); + clientResponse.bufferEntity(); + clientResponse.close(); return clientResponse; 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 565facac..2066b395 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -46,10 +46,10 @@ public class DockerClientTest extends Assert public void beforeTest() throws DockerException { LOG.info("======================= BEFORETEST ======================="); LOG.info("Connecting to Docker server at http://localhost:4243"); - dockerClient = new DockerClient("http://www.nu.nl"); + dockerClient = new DockerClient("http://localhost:4243"); LOG.info("Creating image 'busybox'"); - dockerClient.pull("busybox"); +// dockerClient.pull("busybox"); assertNotNull(dockerClient); LOG.info("======================= END OF BEFORETEST =======================\n\n"); @@ -65,7 +65,7 @@ public void beforeMethod(Method method) { LOG.info(String.format("################################## STARTING %s ##################################", method.getName())); } - @AfterMethod +// @AfterMethod public void afterMethod(ITestResult result) { for (String image : tmpImgs) { LOG.info("Cleaning up temporary image " + image); From 3fda34cca7281442e7ddf176df678cfd3bdd5883 Mon Sep 17 00:00:00 2001 From: Ben Evans Date: Thu, 2 Jan 2014 14:51:26 +0000 Subject: [PATCH 04/72] Initial update --- .../kpelykh/docker/client/DockerClient.java | 1379 +++++++-------- .../docker/client/model/ChangeLog.java | 58 +- .../docker/client/model/CommitConfig.java | 184 +- .../docker/client/model/Container.java | 130 +- .../docker/client/model/ContainerConfig.java | 490 +++--- .../client/model/ContainerCreateResponse.java | 62 +- .../model/ContainerInspectResponse.java | 273 ++- .../docker/client/model/DriverStatus.java | 31 + .../docker/client/model/HostConfig.java | 146 +- .../kpelykh/docker/client/model/IBuilder.java | 9 + .../kpelykh/docker/client/model/Image.java | 108 +- .../client/model/ImageInspectResponse.java | 136 +- .../com/kpelykh/docker/client/model/Info.java | 184 +- .../kpelykh/docker/client/model/Ports.java | 83 + .../docker/client/model/SearchItem.java | 75 +- .../kpelykh/docker/client/model/Version.java | 75 +- .../docker/client/test/DockerClientTest.java | 1536 ++++++++--------- 17 files changed, 2735 insertions(+), 2224 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/model/DriverStatus.java create mode 100644 src/main/java/com/kpelykh/docker/client/model/IBuilder.java create mode 100644 src/main/java/com/kpelykh/docker/client/model/Ports.java diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index e155f53b..46524aa5 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -1,688 +1,691 @@ -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.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.io.FileUtils; -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.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.PoolingClientConnectionManager; -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.util.List; -import java.util.UUID; - -/** - * - * @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.3"; - 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); - - client.addFilter(new JsonClientFilter()); - //client.addFilter(new LoggingFilter()); - } - - /** - ** MISC API - ** - **/ - - public Info info() throws DockerException { - WebResource webResource = client.resource(restEndpointUrl + "/info"); - - try { - LOGGER.trace("GET: " + webResource.toString()); - 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.toString()); - 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.toString()); - 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); - } - } - } - - 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.toString()); - 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(String.format("%s 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.toString()); - String response = webResource.get(String.class); - LOGGER.trace("Response:" + response.toString()); - - 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.toString()); - List images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response:" + images.toString()); - 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 { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); - - try { - LOGGER.trace("GET: " + webResource.toString()); - return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new DockerException(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.toString()); - List containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response:" + containers.toString()); - - return containers; - } - - - public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException { - - WebResource webResource = client.resource(restEndpointUrl + "/containers/create"); - - try { - LOGGER.trace("POST: " + webResource.toString()); - return webResource.accept(MediaType.APPLICATION_JSON) - .type(MediaType.APPLICATION_JSON) - .post(ContainerCreateResponse.class, config); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new DockerException(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 { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); - - try { - LOGGER.trace("POST: " + webResource.toString()); - 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 DockerException(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 { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); - - try { - LOGGER.trace("GET: " + webResource.toString()); - return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); - } catch (UniformInterfaceException exception) { - 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 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.toString()); - 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) { - 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 { - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); - - try { - LOGGER.trace("POST: " + webResource.toString()); - 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 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); - } - } 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 { - 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.toString()); - 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 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 containterDiff(String containerId) throws DockerException { - - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); - - try { - LOGGER.trace("GET: " + webResource.toString()); - return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - } catch (UniformInterfaceException exception) { - 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 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.toString()); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - LOGGER.warn(String.format("No such container %s", 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.toString()); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - LOGGER.warn(String.format("No such container %s", 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 { - WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); - - try { - LOGGER.trace("POST: " + webResource.toString()); - webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); - } catch (UniformInterfaceException exception) { - if (exception.getResponse().getStatus() == 404) { - throw new DockerException(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 { - Preconditions.checkNotNull(commitConfig.container, "Container ID was not specified"); - - MultivaluedMap params = new MultivaluedMapImpl(); - params.add("container", commitConfig.container); - params.add("repo", commitConfig.repo); - params.add("tag", commitConfig.tag); - params.add("m", commitConfig.message); - params.add("author", commitConfig.author); - params.add("run", commitConfig.run); - - WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params); - - try { - LOGGER.trace("POST: " + webResource.toString()); - 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 DockerException(String.format("No such container %s", commitConfig.container)); - } 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 { - 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); - - // 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("Sorce file %s doesnt' exist", src)); - } - if (src.isDirectory()) { - FileUtils.copyDirectory(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.toString()); - 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); - } - - } - -} +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 org.apache.commons.io.FileUtils; +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.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.PoolingClientConnectionManager; +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.util.List; +import java.util.UUID; + +/** + * + * @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.3"; + 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); + + client.addFilter(new JsonClientFilter()); + client.addFilter(new LoggingFilter()); + } + + /** + ** MISC API + ** + **/ + + public Info info() throws DockerException { + WebResource webResource = client.resource(restEndpointUrl + "/info"); + // Add logging +// webResource.addFilter(new com.sun.jersey.api.client.filter.LoggingFilter()); + + try { + LOGGER.trace("GET: " + webResource.toString()); + 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.toString()); + 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.toString()); + 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); + } + } + } + + 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.toString()); + 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(String.format("%s 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.toString()); + String response = webResource.get(String.class); + LOGGER.trace("Response:" + response.toString()); + + 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.toString()); + List images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); + LOGGER.trace("Response:" + images.toString()); + 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 { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); + + try { + LOGGER.trace("GET: " + webResource.toString()); + return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new DockerException(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.toString()); + List containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); + LOGGER.trace("Response:" + containers.toString()); + + return containers; + } + + + public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException { + + WebResource webResource = client.resource(restEndpointUrl + "/containers/create"); + + try { + LOGGER.trace("POST: " + webResource.toString()); + return webResource.accept(MediaType.APPLICATION_JSON) + .type(MediaType.APPLICATION_JSON) + .post(ContainerCreateResponse.class, config); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new DockerException(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 { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); + + try { + LOGGER.trace("POST: " + webResource.toString()); + 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 DockerException(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 { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); + + try { + LOGGER.trace("GET: " + webResource.toString()); + return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); + } catch (UniformInterfaceException exception) { + 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 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.toString()); + 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) { + 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 { + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); + + try { + LOGGER.trace("POST: " + webResource.toString()); + 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 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); + } + } 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 { + 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.toString()); + 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 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 containterDiff(String containerId) throws DockerException { + + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); + + try { + LOGGER.trace("GET: " + webResource.toString()); + return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); + } catch (UniformInterfaceException exception) { + 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 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.toString()); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + LOGGER.warn(String.format("No such container %s", 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.toString()); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + LOGGER.warn(String.format("No such container %s", 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 { + WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); + + try { + LOGGER.trace("POST: " + webResource.toString()); + webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); + } catch (UniformInterfaceException exception) { + if (exception.getResponse().getStatus() == 404) { + throw new DockerException(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 { + 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.toString()); + 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 DockerException(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 { + 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); + + // 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("Sorce file %s doesnt' exist", src)); + } + if (src.isDirectory()) { + FileUtils.copyDirectory(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.toString()); + 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/ChangeLog.java b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java index 1d24f8cf..be6df3a4 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java +++ b/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java @@ -1,25 +1,33 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class ChangeLog { - - @JsonProperty("Path") - public String path; - - @JsonProperty("Kind") - public int kind; - - @Override - public String toString() { - return "ChangeLog{" + - "path='" + path + '\'' + - ", kind=" + kind + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class ChangeLog { + + @JsonProperty("Path") + private String path; + + @JsonProperty("Kind") + private int kind; + + public String getPath() { + return path; + } + + public int getKind() { + return kind; + } + + @Override + public String toString() { + return "ChangeLog{" + + "path='" + path + '\'' + + ", kind=" + kind + + '}'; + } +} 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 bbe53d79..dc5c2c2f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java @@ -1,77 +1,107 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class CommitConfig { - - @JsonProperty("container") public String container; - @JsonProperty("repo") public String repo; - @JsonProperty("tag") public String tag; - @JsonProperty("m") public String message; - - //author (eg. “John Hannibal Smith ”) - @JsonProperty("author") public String author; - - //config automatically applied when the image is run. (ex: {“Cmd”: [“cat”, “/world”], “PortSpecs”:[“22”]}) - @JsonProperty("run") public String run; - - - public CommitConfig() {} - - public CommitConfig(Builder builder) { - this.container = builder.container; - this.repo = builder.repo; - this.tag = builder.tag; - this.message = builder.message; - this.author = builder.author; - this.run = builder.run; - } - - public static class Builder { - private String container; - private String repo; - private String tag; - private String message; - private String author; - private String run; - - public Builder(String containerId) { - this.container = containerId; - } - - public Builder repo(String repo) { - this.repo = repo; - return this; - } - - public Builder tag(String tag) { - this.tag = tag; - return this; - } - - public Builder message(String message) { - this.message = message; - return this; - } - - public Builder author(String author) { - this.author = author; - return this; - } - - public Builder run(String run) { - this.run = run; - return this; - } - - public CommitConfig build() { - return new CommitConfig(this); - } - } - -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class CommitConfig { + + @JsonProperty("container") + private String container; + + @JsonProperty("repo") + private String repo; + + @JsonProperty("tag") + private String tag; + + @JsonProperty("m") + private String message; + + //author (eg. “John Hannibal Smith ”) + @JsonProperty("author") + private String author; + + //config automatically applied when the image is run. (ex: {“Cmd”: [“cat”, “/world”], “PortSpecs”:[“22”]}) + @JsonProperty("run") + private String run; + + public String getContainer() { + return container; + } + + public String getRepo() { + return repo; + } + + public String getTag() { + return tag; + } + + public String getMessage() { + return message; + } + + public String getAuthor() { + return author; + } + + public String getRun() { + return run; + } + + private CommitConfig(Builder b) { + this.container = b.container; + this.repo = b.repo; + this.tag = b.tag; + this.message = b.message; + this.author = b.author; + this.run = b.run; + } + + public static class Builder implements IBuilder { + private String container; + private String repo; + private String tag; + private String message; + private String author; + private String run; + + public Builder(String containerId) { + this.container = containerId; + } + + public Builder repo(String repo) { + this.repo = repo; + return this; + } + + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + public Builder message(String message) { + this.message = message; + return this; + } + + public Builder author(String author) { + this.author = author; + return this; + } + + public Builder run(String run) { + this.run = run; + return this; + } + + public CommitConfig build() { + return new CommitConfig(this); + } + } + +} 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 cef2d3b6..bf1e9a14 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Container.java +++ b/src/main/java/com/kpelykh/docker/client/model/Container.java @@ -1,49 +1,81 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class Container { - - @JsonProperty("Id") - public String id; - - @JsonProperty("Command") - public String command; - - @JsonProperty("Image") - public String image; - - @JsonProperty("Created") - public long created; - - @JsonProperty("Status") - public String status; - - @JsonProperty("Ports") - public String ports; //Example value "49164->6900, 49165->7100" - - @JsonProperty("SizeRw") - public int size; - - @JsonProperty("SizeRootFs") - public int sizeRootFs; - - @Override - public String toString() { - return "Container{" + - "id='" + id + '\'' + - ", command='" + command + '\'' + - ", image='" + image + '\'' + - ", created=" + created + - ", status='" + status + '\'' + - ", ports=" + ports + - ", size=" + size + - ", sizeRootFs=" + sizeRootFs + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class Container { + + @JsonProperty("Id") + private String id; + + @JsonProperty("Command") + private String command; + + @JsonProperty("Image") + private String image; + + @JsonProperty("Created") + private long created; + + @JsonProperty("Status") + private String status; + + @JsonProperty("Ports") + private String ports; //Example value "49164->6900, 49165->7100" + + @JsonProperty("SizeRw") + private int size; + + @JsonProperty("SizeRootFs") + private int sizeRootFs; + + public String getId() { + return id; + } + + public String getCommand() { + return command; + } + + public String getImage() { + return image; + } + + public long getCreated() { + return created; + } + + public String getStatus() { + return status; + } + + public String getPorts() { + return ports; + } + + public int getSize() { + return size; + } + + public int getSizeRootFs() { + return sizeRootFs; + } + + @Override + public String toString() { + return "Container{" + + "id='" + id + '\'' + + ", command='" + command + '\'' + + ", image='" + image + '\'' + + ", created=" + created + + ", status='" + status + '\'' + + ", ports=" + ports + + ", size=" + size + + ", sizeRootFs=" + sizeRootFs + + '}'; + } +} 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 af79ff20..df6c5ee0 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -1,239 +1,251 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -import java.util.Arrays; -import java.util.Map; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class ContainerConfig { - - @JsonProperty("Hostname") private String hostName = ""; - @JsonProperty("PortSpecs") private String[] portSpecs; - @JsonProperty("User") private String user = ""; - @JsonProperty("Tty") private boolean tty = false; - @JsonProperty("OpenStdin") private boolean stdinOpen = false; - @JsonProperty("StdinOnce") private boolean stdInOnce = false; - @JsonProperty("Memory") private long memoryLimit = 0; - @JsonProperty("MemorySwap") private long memorySwap = 0; - @JsonProperty("CpuShares") private int cpuShares = 0; - @JsonProperty("AttachStdin") private boolean attachStdin = false; - @JsonProperty("AttachStdout") private boolean attachStdout = false; - @JsonProperty("AttachStderr") private boolean attachStderr = false; - @JsonProperty("Env") private String[] env; - @JsonProperty("Cmd") private String[] cmd; - @JsonProperty("Dns") private String[] dns; - @JsonProperty("Image") private String image; - @JsonProperty("Volumes") private Object volumes; - @JsonProperty("VolumesFrom") private String volumesFrom = ""; - @JsonProperty("Entrypoint") private String[] entrypoint = new String[]{}; - @JsonProperty("NetworkDisabled") private boolean networkDisabled = false; - @JsonProperty("Privileged") private boolean privileged = false; - @JsonProperty("WorkingDir") private String workingDir = ""; - - - public String getWorkingDir() { - return workingDir; - } - - public void setWorkingDir(String workingDir) { - this.workingDir = workingDir; - } - - public boolean isPrivileged() { - return privileged; - } - - public void setPrivileged(boolean privileged) { - this.privileged = privileged; - } - - public String getHostName() { - return hostName; - } - - public boolean getNetworkDisabled() { - return networkDisabled; - } - - public void setNetworkDisabled(boolean networkDisabled) { - this.networkDisabled = networkDisabled; - } - - public void setHostName(String hostName) { - this.hostName = hostName; - } - - public String[] getPortSpecs() { - return portSpecs; - } - - public void setPortSpecs(String[] portSpecs) { - this.portSpecs = portSpecs; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public boolean isTty() { - return tty; - } - - public void setTty(boolean tty) { - this.tty = tty; - } - - public boolean isStdinOpen() { - return stdinOpen; - } - - public void setStdinOpen(boolean stdinOpen) { - this.stdinOpen = stdinOpen; - } - - public boolean isStdInOnce() { - return stdInOnce; - } - - public void setStdInOnce(boolean stdInOnce) { - this.stdInOnce = stdInOnce; - } - - public long getMemoryLimit() { - return memoryLimit; - } - - public void setMemoryLimit(long memoryLimit) { - this.memoryLimit = memoryLimit; - } - - public long getMemorySwap() { - return memorySwap; - } - - public void setMemorySwap(long memorySwap) { - this.memorySwap = memorySwap; - } - - public int getCpuShares() { - return cpuShares; - } - - public void setCpuShares(int cpuShares) { - this.cpuShares = cpuShares; - } - - public boolean isAttachStdin() { - return attachStdin; - } - - public void setAttachStdin(boolean attachStdin) { - this.attachStdin = attachStdin; - } - - public boolean isAttachStdout() { - return attachStdout; - } - - public void setAttachStdout(boolean attachStdout) { - this.attachStdout = attachStdout; - } - - public boolean isAttachStderr() { - return attachStderr; - } - - public void setAttachStderr(boolean attachStderr) { - this.attachStderr = attachStderr; - } - - public String[] getEnv() { - return env; - } - - public void setEnv(String[] env) { - this.env = env; - } - - public String[] getCmd() { - return cmd; - } - - public void setCmd(String[] cmd) { - this.cmd = cmd; - } - - public String[] getDns() { - return dns; - } - - public void setDns(String[] dns) { - this.dns = dns; - } - - public String getImage() { - return image; - } - - public void setImage(String image) { - this.image = image; - } - - public Object getVolumes() { - return volumes; - } - - public void setVolumes(Object volumes) { - this.volumes = volumes; - } - - public String getVolumesFrom() { - return volumesFrom; - } - - public void setVolumesFrom(String volumesFrom) { - this.volumesFrom = volumesFrom; - } - - public String[] getEntrypoint() { - return entrypoint; - } - - public void setEntrypoint(String[] entrypoint) { - this.entrypoint = entrypoint; - } - - @Override - public String toString() { - return "ContainerConfig{" + - "hostName='" + hostName + '\'' + - ", portSpecs=" + Arrays.toString(portSpecs) + - ", user='" + user + '\'' + - ", tty=" + tty + - ", stdinOpen=" + stdinOpen + - ", stdInOnce=" + stdInOnce + - ", memoryLimit=" + memoryLimit + - ", memorySwap=" + memorySwap + - ", cpuShares=" + cpuShares + - ", attachStdin=" + attachStdin + - ", attachStdout=" + attachStdout + - ", attachStderr=" + attachStderr + - ", env=" + env + - ", cmd=" + Arrays.toString(cmd) + - ", dns=" + Arrays.toString(dns) + - ", image='" + image + '\'' + - ", volumes=" + volumes + - ", volumesFrom='" + volumesFrom + '\'' + - ", entrypoint='" + Arrays.toString(portSpecs) + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Arrays; +import java.util.Map; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class ContainerConfig { + + @JsonProperty("Hostname") private String hostName = ""; + @JsonProperty("PortSpecs") private String[] portSpecs; + @JsonProperty("User") private String user = ""; + @JsonProperty("Tty") private boolean tty = false; + @JsonProperty("OpenStdin") private boolean stdinOpen = false; + @JsonProperty("StdinOnce") private boolean stdInOnce = false; + @JsonProperty("Memory") private long memoryLimit = 0; + @JsonProperty("MemorySwap") private long memorySwap = 0; + @JsonProperty("CpuShares") private int cpuShares = 0; + @JsonProperty("AttachStdin") private boolean attachStdin = false; + @JsonProperty("AttachStdout") private boolean attachStdout = false; + @JsonProperty("AttachStderr") private boolean attachStderr = false; + @JsonProperty("Env") private String[] env; + @JsonProperty("Cmd") private String[] cmd; + @JsonProperty("Dns") private String[] dns; + @JsonProperty("Image") private String image; + @JsonProperty("Volumes") private Object volumes; + @JsonProperty("VolumesFrom") private String volumesFrom = ""; + @JsonProperty("Entrypoint") private String[] entrypoint = new String[]{}; + @JsonProperty("NetworkDisabled") private boolean networkDisabled = false; + @JsonProperty("Privileged") private boolean privileged = false; + @JsonProperty("WorkingDir") private String workingDir = ""; + @JsonProperty("Domainname") private String domainName = ""; + // FIXME Is this the right type? -BJE + @JsonProperty("ExposedPorts") private Map exposedPorts; + + public Map getExposedPorts() { + return exposedPorts; + } + + public boolean isNetworkDisabled() { + return networkDisabled; + } + + public String getDomainName() { + return domainName; + } + + public String getWorkingDir() { return workingDir; } + + public void setWorkingDir(String workingDir) { + this.workingDir = workingDir; + } + + public boolean isPrivileged() { + return privileged; + } + + public void setPrivileged(boolean privileged) { + this.privileged = privileged; + } + + public String getHostName() { + return hostName; + } + + public void setNetworkDisabled(boolean networkDisabled) { + this.networkDisabled = networkDisabled; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String[] getPortSpecs() { + return portSpecs; + } + + public void setPortSpecs(String[] portSpecs) { + this.portSpecs = portSpecs; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public boolean isTty() { + return tty; + } + + public void setTty(boolean tty) { + this.tty = tty; + } + + public boolean isStdinOpen() { + return stdinOpen; + } + + public void setStdinOpen(boolean stdinOpen) { + this.stdinOpen = stdinOpen; + } + + public boolean isStdInOnce() { + return stdInOnce; + } + + public void setStdInOnce(boolean stdInOnce) { + this.stdInOnce = stdInOnce; + } + + public long getMemoryLimit() { + return memoryLimit; + } + + public void setMemoryLimit(long memoryLimit) { + this.memoryLimit = memoryLimit; + } + + public long getMemorySwap() { + return memorySwap; + } + + public void setMemorySwap(long memorySwap) { + this.memorySwap = memorySwap; + } + + public int getCpuShares() { + return cpuShares; + } + + public void setCpuShares(int cpuShares) { + this.cpuShares = cpuShares; + } + + public boolean isAttachStdin() { + return attachStdin; + } + + public void setAttachStdin(boolean attachStdin) { + this.attachStdin = attachStdin; + } + + public boolean isAttachStdout() { + return attachStdout; + } + + public void setAttachStdout(boolean attachStdout) { + this.attachStdout = attachStdout; + } + + public boolean isAttachStderr() { + return attachStderr; + } + + public void setAttachStderr(boolean attachStderr) { + this.attachStderr = attachStderr; + } + + public String[] getEnv() { + return env; + } + + public void setEnv(String[] env) { + this.env = env; + } + + public String[] getCmd() { + return cmd; + } + + public void setCmd(String[] cmd) { + this.cmd = cmd; + } + + public String[] getDns() { + return dns; + } + + public void setDns(String[] dns) { + this.dns = dns; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public Object getVolumes() { + return volumes; + } + + public void setVolumes(Object volumes) { + this.volumes = volumes; + } + + public String getVolumesFrom() { + return volumesFrom; + } + + public void setVolumesFrom(String volumesFrom) { + this.volumesFrom = volumesFrom; + } + + public String[] getEntrypoint() { + return entrypoint; + } + + public void setEntrypoint(String[] entrypoint) { + this.entrypoint = entrypoint; + } + + @Override + public String toString() { + return "ContainerConfig{" + + "hostName='" + hostName + '\'' + + ", portSpecs=" + Arrays.toString(portSpecs) + + ", user='" + user + '\'' + + ", tty=" + tty + + ", stdinOpen=" + stdinOpen + + ", stdInOnce=" + stdInOnce + + ", memoryLimit=" + memoryLimit + + ", memorySwap=" + memorySwap + + ", cpuShares=" + cpuShares + + ", attachStdin=" + attachStdin + + ", attachStdout=" + attachStdout + + ", attachStderr=" + attachStderr + + ", env=" + Arrays.toString(env) + + ", cmd=" + Arrays.toString(cmd) + + ", dns=" + Arrays.toString(dns) + + ", image='" + image + '\'' + + ", volumes=" + volumes + + ", volumesFrom='" + volumesFrom + '\'' + + ", entrypoint=" + Arrays.toString(entrypoint) + + ", networkDisabled=" + networkDisabled + + ", privileged=" + privileged + + ", workingDir='" + workingDir + '\'' + + ", domainName='" + domainName + '\'' + + '}'; + } +} 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 1baf3dc2..c0ef5bdc 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java @@ -1,27 +1,35 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -import java.util.Arrays; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class ContainerCreateResponse { - - @JsonProperty("Id") - public String id; - - @JsonProperty("Warnings") - public String[] warnings; - - @Override - public String toString() { - return "ContainerCreateResponse{" + - "id='" + id + '\'' + - ", warnings=" + Arrays.toString(warnings) + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Arrays; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class ContainerCreateResponse { + + @JsonProperty("Id") + private String id; + + @JsonProperty("Warnings") + private String[] warnings; + + public String getId() { + return id; + } + + public String[] getWarnings() { + return warnings; + } + + @Override + public String toString() { + return "ContainerCreateResponse{" + + "id='" + id + '\'' + + ", warnings=" + Arrays.toString(warnings) + + '}'; + } +} 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 b3ec431e..acf92e98 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -1,78 +1,195 @@ -package com.kpelykh.docker.client.model; - - -import org.codehaus.jackson.annotate.JsonProperty; - -import java.util.Arrays; -import java.util.Map; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class ContainerInspectResponse { - - @JsonProperty("ID") public String id; - @JsonProperty("Created") public String created; - @JsonProperty("Path") public String path; - @JsonProperty("Args") public String[] args; - @JsonProperty("Config") public ContainerConfig config; - @JsonProperty("State") public ContainerState state; - @JsonProperty("Image") public String image; - @JsonProperty("NetworkSettings") public NetworkSettings networkSettings; - @JsonProperty("SysInitPath") public String sysInitPath; - @JsonProperty("ResolvConfPath") public String resolvConfPath; - @JsonProperty("Volumes") public Map volumes; - @JsonProperty("VolumesRW") public Map volumesRW; - - @Override - public String toString() { - return "ContainerInspectResponse{" + - "volumes=" + volumes + - ", volumesRW=" + volumesRW + '\'' + - ", resolvConfPath='" + resolvConfPath + '\'' + - ", sysInitPath='" + sysInitPath + '\'' + - ", id='" + id + '\'' + - ", created='" + created + '\'' + - ", path='" + path + '\'' + - ", args=" + Arrays.toString(args) + - ", config=" + config + - ", state=" + state + - ", image='" + image + '\'' + - ", networkSettings=" + networkSettings + - '}'; - } - - public class NetworkSettings { - - @JsonProperty("IPAddress") public String ipAddress; - @JsonProperty("IPPrefixLen") public int ipPrefixLen; - @JsonProperty("Gateway") public String gateway; - @JsonProperty("Bridge") public String bridge; - @JsonProperty("PortMapping") public Map> portMapping; - } - - public class ContainerState { - - @JsonProperty("Running") public boolean running; - @JsonProperty("Pid") public int pid; - @JsonProperty("ExitCode") public int exitCode; - @JsonProperty("StartedAt") public String startedAt; - @JsonProperty("Ghost") public boolean ghost; - - @Override - public String toString() { - return "ContainerState{" + - "running=" + running + - ", pid=" + pid + - ", exitCode=" + exitCode + - ", startedAt='" + startedAt + '\'' + - ", ghost=" + ghost + - '}'; - } - - - } - -} +package com.kpelykh.docker.client.model; + + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Arrays; +import java.util.Map; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class ContainerInspectResponse { + + @JsonProperty("ID") + private String id; + + @JsonProperty("Created") + private String created; + + @JsonProperty("Path") + private String path; + + @JsonProperty("Args") + private String[] args; + + @JsonProperty("Config") + public ContainerConfig config; + + @JsonProperty("State") + private ContainerState state; + + @JsonProperty("Image") + private String image; + + @JsonProperty("NetworkSettings") + private NetworkSettings networkSettings; + + @JsonProperty("SysInitPath") + private String sysInitPath; + + @JsonProperty("ResolvConfPath") + private String resolvConfPath; + + @JsonProperty("Volumes") + private Map volumes; + + @JsonProperty("VolumesRW") + private Map volumesRW; + + @JsonProperty("HostnamePath") + private String hostnamePath; + + @JsonProperty("HostsPath") + private String hostsPath; + + @JsonProperty("Name") + private String name; + + @JsonProperty("Driver") + private String driver; + + public String getDriver() { + return driver; + } + + public String getHostnamePath() { + return hostnamePath; + } + + public String getHostsPath() { + return hostsPath; + } + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public String getCreated() { + return created; + } + + public String getPath() { + return path; + } + + public String[] getArgs() { + return args; + } + + public ContainerConfig getConfig() { + return config; + } + + public ContainerState getState() { + return state; + } + + public String getImage() { + return image; + } + + public NetworkSettings getNetworkSettings() { + return networkSettings; + } + + public String getSysInitPath() { + return sysInitPath; + } + + public String getResolvConfPath() { + return resolvConfPath; + } + + public Map getVolumes() { + return volumes; + } + + public Map getVolumesRW() { + return volumesRW; + } + + @Override + public String toString() { + return "ContainerInspectResponse{" + + "id='" + id + '\'' + + ", created='" + created + '\'' + + ", path='" + path + '\'' + + ", args=" + Arrays.toString(args) + + ", config=" + config + + ", state=" + state + + ", image='" + image + '\'' + + ", networkSettings=" + networkSettings + + ", sysInitPath='" + sysInitPath + '\'' + + ", resolvConfPath='" + resolvConfPath + '\'' + + ", volumes=" + volumes + + ", volumesRW=" + volumesRW + + ", hostnamePath='" + hostnamePath + '\'' + + ", hostsPath='" + hostsPath + '\'' + + ", name='" + name + '\'' + + ", driver='" + driver + '\'' + + '}'; + } + + public class NetworkSettings { + + @JsonProperty("IPAddress") public String ipAddress; + @JsonProperty("IPPrefixLen") public int ipPrefixLen; + @JsonProperty("Gateway") public String gateway; + @JsonProperty("Bridge") public String bridge; + // Deprecated - can we remove? +// @JsonProperty("PortMapping") public Map> portMapping; + // FIXME Is this the right type? -BJE + @JsonProperty("Ports") public Map ports; + + @Override + public String toString() { + return "NetworkSettings{" + + "ipAddress='" + ipAddress + '\'' + + ", ipPrefixLen=" + ipPrefixLen + + ", gateway='" + gateway + '\'' + + ", bridge='" + bridge + '\'' + + ", ports=" + ports + + '}'; + } + } + + public class ContainerState { + + @JsonProperty("Running") public boolean running; + @JsonProperty("Pid") public int pid; + @JsonProperty("ExitCode") public int exitCode; + @JsonProperty("StartedAt") public String startedAt; + @JsonProperty("Ghost") public boolean ghost; + @JsonProperty("FinishedAt") private String finishedAt; + + @Override + public String toString() { + return "ContainerState{" + + "running=" + running + + ", pid=" + pid + + ", exitCode=" + exitCode + + ", startedAt='" + startedAt + '\'' + + ", ghost=" + ghost + + ", finishedAt='" + finishedAt + '\'' + + '}'; + } + } + +} diff --git a/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java new file mode 100644 index 00000000..2ed1922c --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java @@ -0,0 +1,31 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Created by ben on 12/12/13. + */ +public class DriverStatus { + + @JsonProperty("Root Dir") + private String rootDir; + + @JsonProperty("Dirs") + private int dirs; + + public String getRootDir() { + return rootDir; + } + + public int getDirs() { + return dirs; + } + + @Override + public String toString() { + return "DriverStatus{" + + "rootDir='" + rootDir + '\'' + + ", dirs=" + dirs + + '}'; + } +} 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 e9351270..45fee6e7 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -1,73 +1,73 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class HostConfig { - - @JsonProperty("Binds") - public String[] binds; - - @JsonProperty("ContainerIDFile") - public String containerIDFile; - - @JsonProperty("LxcConf") - public LxcConf[] lxcConf; - - public HostConfig(String[] binds) { - this.binds = binds; - } - - public String[] getBinds() { - return binds; - } - - public void setBinds(String[] binds) { - this.binds = binds; - } - - public String getContainerIDFile() { - return containerIDFile; - } - - public void setContainerIDFile(String containerIDFile) { - this.containerIDFile = containerIDFile; - } - - public LxcConf[] getLxcConf() { - return lxcConf; - } - - public void setLxcConf(LxcConf[] lxcConf) { - this.lxcConf = lxcConf; - } - - public class LxcConf { - @JsonProperty("Key") - public String key; - - @JsonProperty("Value") - public String value; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class HostConfig { + + @JsonProperty("Binds") + private String[] binds; + + @JsonProperty("ContainerIDFile") + private String containerIDFile; + + @JsonProperty("LxcConf") + private LxcConf[] lxcConf; + + public HostConfig(String[] binds) { + this.binds = binds; + } + + public String[] getBinds() { + return binds; + } + + public void setBinds(String[] binds) { + this.binds = binds; + } + + public String getContainerIDFile() { + return containerIDFile; + } + + public void setContainerIDFile(String containerIDFile) { + this.containerIDFile = containerIDFile; + } + + public LxcConf[] getLxcConf() { + return lxcConf; + } + + public void setLxcConf(LxcConf[] lxcConf) { + this.lxcConf = lxcConf; + } + + public class LxcConf { + @JsonProperty("Key") + public String key; + + @JsonProperty("Value") + public String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + } +} diff --git a/src/main/java/com/kpelykh/docker/client/model/IBuilder.java b/src/main/java/com/kpelykh/docker/client/model/IBuilder.java new file mode 100644 index 00000000..7f5f1606 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/IBuilder.java @@ -0,0 +1,9 @@ +package com.kpelykh.docker.client.model; + +/** + * Created by ben on 12/12/13. + */ +public interface IBuilder { + + T build(); +} 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 7f199f11..ac0c4a7e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Image.java +++ b/src/main/java/com/kpelykh/docker/client/model/Image.java @@ -1,42 +1,66 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class Image { - - @JsonProperty("Repository") - public String repository; - - @JsonProperty("Tag") - public String tag; - - @JsonProperty("Id") - public String id; - - @JsonProperty("Created") - public long created; - - @JsonProperty("Size") - public long size; - - @JsonProperty("VirtualSize") - public long virtualSize; - - @Override - public String toString() { - return "Image{" + - "repository='" + repository + '\'' + - ", tag='" + tag + '\'' + - ", id='" + id + '\'' + - ", created=" + created + - ", size=" + size + - ", virtualSize=" + virtualSize + - '}'; - } - -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class Image { + + @JsonProperty("Repository") + private String repository; + + @JsonProperty("Tag") + private String tag; + + @JsonProperty("Id") + private String id; + + @JsonProperty("Created") + private long created; + + @JsonProperty("Size") + private long size; + + @JsonProperty("VirtualSize") + private long virtualSize; + + public String getRepository() { + return repository; + } + + public String getTag() { + return tag; + } + + public String getId() { + return id; + } + + public long getCreated() { + return created; + } + + public long getSize() { + return size; + } + + public long getVirtualSize() { + return virtualSize; + } + + @Override + public String toString() { + return "Image{" + + "repository='" + repository + '\'' + + ", tag='" + tag + '\'' + + ", id='" + id + '\'' + + ", created=" + created + + ", size=" + size + + ", virtualSize=" + virtualSize + + '}'; + } + +} 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 176533be..33c7cfb7 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java @@ -1,41 +1,95 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class ImageInspectResponse { - - @JsonProperty("id") public String id; - @JsonProperty("parent") public String parent; - @JsonProperty("created") public String created; - @JsonProperty("container") public String container; - @JsonProperty("container_config") public ContainerConfig containerConfig; - @JsonProperty("Size") public int size; - @JsonProperty("docker_version") public String dockerVersion; - @JsonProperty("config") public ContainerConfig config; - @JsonProperty("architecture") public String arch; - @JsonProperty("comment") public String comment; - @JsonProperty("author") public String author; - - - @Override - public String toString() { - return "ImageInspectResponse{" + - "id='" + id + '\'' + - ", parent='" + parent + '\'' + - ", created='" + created + '\'' + - ", container='" + container + '\'' + - ", containerConfig=" + containerConfig + - ", size=" + size + - ", dockerVersion='" + dockerVersion + '\'' + - ", config=" + config + - ", arch='" + arch + '\'' + - ", comment='" + comment + '\'' + - ", author='" + author + '\'' + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class ImageInspectResponse { + + @JsonProperty("id") + private String id; + + @JsonProperty("parent") private String parent; + + @JsonProperty("created") private String created; + + @JsonProperty("container") private String container; + + @JsonProperty("container_config") private ContainerConfig containerConfig; + + @JsonProperty("Size") private int size; + + @JsonProperty("docker_version") private String dockerVersion; + + @JsonProperty("config") private ContainerConfig config; + + @JsonProperty("architecture") private String arch; + + @JsonProperty("comment") private String comment; + + @JsonProperty("author") private String author; + + public String getId() { + return id; + } + + public String getParent() { + return parent; + } + + public String getCreated() { + return created; + } + + public String getContainer() { + return container; + } + + public ContainerConfig getContainerConfig() { + return containerConfig; + } + + public int getSize() { + return size; + } + + public String getDockerVersion() { + return dockerVersion; + } + + public ContainerConfig getConfig() { + return config; + } + + public String getArch() { + return arch; + } + + public String getComment() { + return comment; + } + + public String getAuthor() { + return author; + } + + @Override + public String toString() { + return "ImageInspectResponse{" + + "id='" + id + '\'' + + ", parent='" + parent + '\'' + + ", created='" + created + '\'' + + ", container='" + container + '\'' + + ", containerConfig=" + containerConfig + + ", size=" + size + + ", dockerVersion='" + dockerVersion + '\'' + + ", config=" + config + + ", arch='" + arch + '\'' + + ", comment='" + comment + '\'' + + ", author='" + author + '\'' + + '}'; + } +} 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 bfa394c7..a38b73c0 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -1,62 +1,122 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class Info { - - @JsonProperty("Debug") - public boolean debug; - - @JsonProperty("Containers") - public int containers; - - @JsonProperty("Images") - public int images; - - @JsonProperty("NFd") - public int NFd; - - @JsonProperty("NGoroutines") - public int NGoroutines; - - @JsonProperty("MemoryLimit") - public boolean memoryLimit; - - @JsonProperty("LXCVersion") - public String lxcVersion; - - - @JsonProperty("NEventsListener") - public long nEventListener; - - @JsonProperty("KernelVersion") - public String kernelVersion; - - @JsonProperty("IPv4Forwarding") - public String IPv4Forwarding; - - @JsonProperty("IndexServerAddress") - public String IndexServerAddress; - - @Override - public String toString() { - return "Info{" + - "debug=" + debug + - ", containers=" + containers + - ", images=" + images + - ", NFd=" + NFd + - ", NGoroutines=" + NGoroutines + - ", memoryLimit=" + memoryLimit + - ", lxcVersion='" + lxcVersion + '\'' + - ", nEventListener=" + nEventListener + - ", kernelVersion='" + kernelVersion + '\'' + - ", IPv4Forwarding='" + IPv4Forwarding + '\'' + - ", IndexServerAddress='" + IndexServerAddress + '\'' + - '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.List; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class Info { + + @JsonProperty("Debug") + private boolean debug; + + @JsonProperty("Containers") + private int containers; + + @JsonProperty("Driver") + private String driver; + + @JsonProperty("DriverStatus") + private List driverStatuses; + + + @JsonProperty("Images") + private int images; + + @JsonProperty("IPv4Forwarding") + private String IPv4Forwarding; + + @JsonProperty("IndexServerAddress") + private String IndexServerAddress; + + @JsonProperty("KernelVersion") + private String kernelVersion; + + @JsonProperty("LXCVersion") + private String lxcVersion; + + @JsonProperty("MemoryLimit") + private boolean memoryLimit; + + @JsonProperty("NEventsListener") + private long nEventListener; + + @JsonProperty("NFd") + private int NFd; + + @JsonProperty("NGoroutines") + private int NGoroutines; + + public boolean isDebug() { + return debug; + } + + public int getContainers() { + return containers; + } + + public String getDriver() { + return driver; + } + + public List getDriverStatuses() { + return driverStatuses; + } + + public int getImages() { + return images; + } + + public String getIPv4Forwarding() { + return IPv4Forwarding; + } + + public String getIndexServerAddress() { + return IndexServerAddress; + } + + public String getKernelVersion() { + return kernelVersion; + } + + public String getLxcVersion() { + return lxcVersion; + } + + public boolean isMemoryLimit() { + return memoryLimit; + } + + public long getnEventListener() { + return nEventListener; + } + + public int getNFd() { + return NFd; + } + + public int getNGoroutines() { + return NGoroutines; + } + + @Override + public String toString() { + return "Info{" + + "debug=" + debug + + ", containers=" + containers + + ", images=" + images + + ", NFd=" + NFd + + ", NGoroutines=" + NGoroutines + + ", memoryLimit=" + memoryLimit + + ", lxcVersion='" + lxcVersion + '\'' + + ", nEventListener=" + nEventListener + + ", kernelVersion='" + kernelVersion + '\'' + + ", IPv4Forwarding='" + IPv4Forwarding + '\'' + + ", IndexServerAddress='" + IndexServerAddress + '\'' + + '}'; + } +} diff --git a/src/main/java/com/kpelykh/docker/client/model/Ports.java b/src/main/java/com/kpelykh/docker/client/model/Ports.java new file mode 100644 index 00000000..fee9d5be --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/Ports.java @@ -0,0 +1,83 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.ObjectCodec; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by ben on 16/12/13. + */ +@JsonDeserialize(using=Ports.Deserializer.class) +public class Ports { + private final Map ports = new HashMap<>(); + private Port[] mapping; + + private Ports() { } + + private void addPort(Port port) { + ports.put(port.getPort(), port); + } + + private void addMapping(Port src, Port target) { + Port p = ports.get(src); + if (p==null) return; +// p.addMapping(target); + } + + public static class Port{ + private final String scheme; + private final String port; + + public Port(String scheme_, String port_) { + scheme = scheme_; + port = port_; + } + + public String getScheme() { + return scheme; + } + + public String getPort() { + return port; + } + + public static Port makePort(String full) { + if (full == null) return null; + String[] pieces = full.split("/"); + return new Port(pieces[1], pieces[0]); + } + + @Override + public String toString() { + return "Port{" + + "scheme='" + scheme + '\'' + + ", port='" + port + '\'' + + '}'; + } + } + + public static class Deserializer extends JsonDeserializer { + @Override + public Ports deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + Ports out = new Ports(); + ObjectCodec oc = jsonParser.getCodec(); + JsonNode node = oc.readTree(jsonParser); + for (Iterator it = node.getFieldNames(); it.hasNext();) { + String pname = it.next(); + out.addPort(Port.makePort(pname)); + + } + return out; + } + } + +} 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 ff7bbe63..9c0942ea 100644 --- a/src/main/java/com/kpelykh/docker/client/model/SearchItem.java +++ b/src/main/java/com/kpelykh/docker/client/model/SearchItem.java @@ -1,23 +1,52 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class SearchItem { - - @JsonProperty("Name") - public String name; - - @JsonProperty("Description") - public String description; - - @Override - public String toString() { - return "name='" + name + '\'' + - ", description='" + description + '\'' + '}'; - } -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class SearchItem { + + @JsonProperty("star_count") + private int starCount; + + @JsonProperty("is_official") + private boolean isOfficial; + + @JsonProperty("is_trusted") + private boolean isTrusted; + + @JsonProperty("name") + private String name; + + @JsonProperty("description") + private String description; + + public int getStarCount() { + return starCount; + } + + public boolean isOfficial() { + return isOfficial; + } + + public boolean isTrusted() { + return isTrusted; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + return "name='" + name + '\'' + + ", description='" + description + '\'' + '}'; + } +} 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 3fcaaac1..b81f0953 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -1,32 +1,43 @@ -package com.kpelykh.docker.client.model; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * - * @author Konstantin Pelykh (kpelykh@gmail.com) - * - */ -public class Version { - - - @JsonProperty("Version") - public String version; - - @JsonProperty("GitCommit") - public String gitCommit; - - @JsonProperty("GoVersion") - public String goVersion; - - - @Override - public String toString() { - return "Version{" + - "version='" + version + '\'' + - ", gitCommit='" + gitCommit + '\'' + - ", goVersion='" + goVersion + '\'' + - '}'; - } - -} +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * + * @author Konstantin Pelykh (kpelykh@gmail.com) + * + */ +public class Version { + + + @JsonProperty("Version") + private String version; + + @JsonProperty("GitCommit") + private String gitCommit; + + @JsonProperty("GoVersion") + private String goVersion; + + public String getVersion() { + return version; + } + + public String getGitCommit() { + return gitCommit; + } + + public String getGoVersion() { + return goVersion; + } + + @Override + public String toString() { + return "Version{" + + "version='" + version + '\'' + + ", gitCommit='" + gitCommit + '\'' + + ", goVersion='" + goVersion + '\'' + + '}'; + } + +} 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 ca37013b..17b0900b 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -1,769 +1,769 @@ -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 java.io.*; -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.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 ======================="); - LOG.info("Connecting to Docker server at http://localhost:4243"); - dockerClient = new DockerClient("http://localhost:4243"); - 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 image : tmpImgs) { - LOG.info("Cleaning up temporary image " + image); - try { - dockerClient.removeImage(image); - } catch (DockerException ignore) {} - } - - for (String container : tmpContainers) { - LOG.info("Cleaning up temporary container " + container); - try { - dockerClient.removeContainer(container); - } catch (DockerException ignore) {} - } - LOG.info(String.format("################################## END OF %s ##################################\n", result.getName())); - } - - /* - * ######################### - * ## INFORMATION TESTS ## - * ######################### - */ - - @Test - public void testDockerVersion() throws DockerException { - Version version = dockerClient.version(); - LOG.info(version.toString()); - - assertTrue(version.goVersion.length() > 0); - assertTrue(version.version.length() > 0); - - assertEquals(StringUtils.split(version.version, ".").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.containers > 0); - assertTrue(dockerInfo.images > 0); - assertTrue(dockerInfo.NFd > 0); - assertTrue(dockerInfo.NGoroutines > 0); - assertTrue(dockerInfo.memoryLimit); - } - - @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(false); - assertThat(images, notNullValue()); - LOG.info("Images List: " + images); - Info info = dockerClient.info(); - - //assertThat(images.size(), equalTo(info.images)); - - Image img = images.get(0); - assertThat(img.created, is(greaterThan(0L)) ); - assertThat(img.size, is(greaterThan(0L)) ); - assertThat(img.virtualSize, is(greaterThan(0L)) ); - assertThat(img.id, not(isEmptyString())); - assertThat(img.tag, not(isEmptyString())); - assertThat(img.repository, 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.id, not(isEmptyString())); - dockerClient.startContainer(container1.id); - tmpContainers.add(container1.id); - - List containers2 = dockerClient.listContainers(true); - assertThat(size + 1, is(equalTo(containers2.size()))); - Matcher matcher = hasItem(hasField("id", startsWith(container1.id))); - assertThat(containers2, matcher); - - List filteredContainers = filter(hasField("id", startsWith(container1.id)), containers2); - assertThat(filteredContainers.size(), is(equalTo(1))); - - Container container2 = filteredContainers.get(0); - assertThat(container2.command, not(isEmptyString())); - assertThat(container2.image, 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.id, not(isEmptyString())); - - tmpContainers.add(container.id); - } - - @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.id, not(isEmptyString())); - tmpContainers.add(container.id); - - dockerClient.startContainer(container.id); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect: " + containerInspectResponse.toString()); - - assertThat(containerInspectResponse.config, is(notNullValue())); - assertThat(containerInspectResponse.id, not(isEmptyString())); - - assertThat(containerInspectResponse.id, startsWith(container.id)); - - assertThat(containerInspectResponse.image, not(isEmptyString())); - assertThat(containerInspectResponse.state, is(notNullValue())); - - assertThat(containerInspectResponse.state.running, is(true)); - - if (!containerInspectResponse.state.running) { - assertThat(containerInspectResponse.state.exitCode, is(equalTo(0))); - } - - } - - @Test - public void testWaitContainer() 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.id, not(isEmptyString())); - tmpContainers.add(container.id); - - dockerClient.startContainer(container.id); - - int exitCode = dockerClient.waitContainer(container.id); - LOG.info("Container exit code: " + exitCode); - - assertThat(exitCode, equalTo(0)); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect: " + containerInspectResponse.toString()); - - assertThat(containerInspectResponse.state.running, is(equalTo(false))); - assertThat(containerInspectResponse.state.exitCode, is(equalTo(exitCode))); - - } - - @Test - public void testLogs() throws DockerException, IOException { - - String snippet = "hello world"; - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"/bin/echo", snippet}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); - assertThat(container.id, not(isEmptyString())); - - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - int exitCode = dockerClient.waitContainer(container.id); - - assertThat(exitCode, equalTo(0)); - - ClientResponse response = dockerClient.logContainer(container.id); - - 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, equalTo(snippet)); - } - - @Test - public void testDiff() throws DockerException { - 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.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - int exitCode = dockerClient.waitContainer(container.id); - assertThat(exitCode, equalTo(0)); - - List filesystemDiff = dockerClient.containterDiff(container.id); - LOG.info("Container DIFF: " + filesystemDiff.toString()); - - assertThat(filesystemDiff.size(), equalTo(4)); - ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); - - assertThat(testChangeLog, hasField("path", equalTo("/test"))); - assertThat(testChangeLog, hasField("kind", equalTo(1))); - } - - @Test - public void testStopContainer() throws DockerException { - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); - assertThat(container.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - LOG.info("Stopping container " + container.id); - dockerClient.stopContainer(container.id, 2); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); - - assertThat(containerInspectResponse.state.running, is(equalTo(false))); - assertThat(containerInspectResponse.state.exitCode, not(equalTo(0))); - } - - @Test - public void testKillContainer() throws DockerException { - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); - assertThat(container.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - LOG.info("Killing container " + container.id); - dockerClient.kill(container.id); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); - - assertThat(containerInspectResponse.state.running, is(equalTo(false))); - assertThat(containerInspectResponse.state.exitCode, not(equalTo(0))); - - } - - @Test - public void restartContainer() throws DockerException { - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"sleep", "9999"}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); - assertThat(container.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); - - String startTime = containerInspectResponse.state.startedAt; - - dockerClient.restart(container.id, 2); - - ContainerInspectResponse containerInspectResponse2 = dockerClient.inspectContainer(container.id); - LOG.info("Container Inspect After Restart:" + containerInspectResponse2.toString()); - - String startTime2 = containerInspectResponse2.state.startedAt; - - assertThat(startTime, not(equalTo(startTime2))); - - assertThat(containerInspectResponse.state.running, is(equalTo(true))); - - dockerClient.kill(container.id); - } - - @Test - public void removeContainer() throws DockerException { - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage("busybox"); - containerConfig.setCmd(new String[] {"true"}); - - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - - dockerClient.startContainer(container.id); - dockerClient.waitContainer(container.id); - tmpContainers.add(container.id); - - LOG.info("Removing container " + container.id); - dockerClient.removeContainer(container.id); - - List containers2 = dockerClient.listContainers(true); - Matcher matcher = not(hasItem(hasField("id", startsWith(container.id)))); - assertThat(containers2, matcher); - - } - - /* - * ################## - * ## IMAGES TESTS ## - * ################## - * */ - - @Test - public void testPullImage() throws DockerException, IOException { - - String testImage = "joffrey/test001"; - - LOG.info("Removing image " + testImage); - dockerClient.removeImage(testImage); - - Info info = dockerClient.info(); - LOG.info("Client info " + info.toString()); - - int imgCount= info.images; - - LOG.info("Pulling image " + 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("Pulling repository joffrey/test001")); - - tmpImgs.add(testImage); - - info = dockerClient.info(); - LOG.info("Client info after pull " + info.toString()); - - assertThat(imgCount + 2, equalTo(info.images)); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(testImage); - LOG.info("Image Inspect: " + imageInspectResponse.toString()); - assertThat(imageInspectResponse, notNullValue()); - } - - - @Test - public void commitImage() throws DockerException { - - 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.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - LOG.info("Commiting container " + container.toString()); - String imageId = dockerClient.commit(new CommitConfig.Builder(container.id).build()); - tmpImgs.add(imageId); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - LOG.info("Image Inspect: " + imageInspectResponse.toString()); - - assertThat(imageInspectResponse, hasField("container", startsWith(container.id))); - assertThat(imageInspectResponse.containerConfig.getImage(), equalTo("busybox")); - - ImageInspectResponse busyboxImg = dockerClient.inspectImage("busybox"); - - assertThat(imageInspectResponse.parent, equalTo(busyboxImg.id)); - } - - @Test - public void testRemoveImage() throws DockerException { - - - 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.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - - LOG.info("Commiting container " + container.toString()); - String imageId = dockerClient.commit(new CommitConfig.Builder(container.id).build()); - tmpImgs.add(imageId); - - 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.id); - tmpContainers.add(container.id); - int exitcode = dockerClient.waitContainer(container.id); - assertThat(exitcode, equalTo(0)); - } - } - - - @Test - public void testNgixDockerfileBuilder() 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.substringAfterLast(fullLog, "Successfully built ").trim(); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect:" + imageInspectResponse.toString()); - tmpImgs.add(imageInspectResponse.id); - - assertThat(imageInspectResponse.author, 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.substringAfterLast(fullLog, "Successfully built ").trim(); - - ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); - assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect:" + imageInspectResponse.toString()); - tmpImgs.add(imageInspectResponse.id); - - ContainerConfig containerConfig = new ContainerConfig(); - containerConfig.setImage(imageInspectResponse.id); - ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - assertThat(container.id, not(isEmptyString())); - dockerClient.startContainer(container.id); - tmpContainers.add(container.id); - - ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.id); - - assertThat(containerInspectResponse.id, notNullValue()); - assertThat(containerInspectResponse.networkSettings.portMapping, notNullValue()); - int port = Integer.valueOf(containerInspectResponse.networkSettings.portMapping.get("Tcp").get("6900")); - - - LOG.info("Checking port {} is open", port); - assertThat(available(port), is(false)); - - dockerClient.stopContainer(container.id, 0); - - LOG.info("Checking port {} is closed", port); - assertThat(available(port), is(true)); - - } - - - // 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.substringAfterLast(fullLog, "Successfully built ").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.id, not(isEmptyString())); - - dockerClient.startContainer(container.id); - dockerClient.waitContainer(container.id); - - tmpContainers.add(container.id); - - //Log container - ClientResponse logResponse = dockerClient.logContainer(container.id); - - 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(), equalTo(expectedText)); - } +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 java.io.*; +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.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 ======================="); + LOG.info("Connecting to Docker server at http://localhost:4243"); + dockerClient = new DockerClient("http://172.16.2.150:7979"); + 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 image : tmpImgs) { + LOG.info("Cleaning up temporary image " + image); + try { + dockerClient.removeImage(image); + } catch (DockerException ignore) {} + } + + for (String container : tmpContainers) { + LOG.info("Cleaning up temporary container " + container); + try { + dockerClient.removeContainer(container); + } catch (DockerException ignore) {} + } + LOG.info(String.format("################################## END OF %s ##################################\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(false); + assertThat(images, notNullValue()); + LOG.info("Images List: " + images); + Info info = dockerClient.info(); + + //assertThat(images.size(), equalTo(info.images)); + + Image img = images.get(0); + assertThat(img.getCreated(), is(greaterThan(0L)) ); + assertThat(img.getSize(), 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())); + + assertThat(containerInspectResponse.getState().running, is(true)); + + if (!containerInspectResponse.getState().running) { + assertThat(containerInspectResponse.getState().exitCode, is(equalTo(0))); + } + + } + + @Test + public void testWaitContainer() 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()); + + dockerClient.startContainer(container.getId()); + + int exitCode = dockerClient.waitContainer(container.getId()); + LOG.info("Container exit code: " + exitCode); + + assertThat(exitCode, equalTo(0)); + + ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); + LOG.info("Container Inspect: " + containerInspectResponse.toString()); + + assertThat(containerInspectResponse.getState().running, is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, is(equalTo(exitCode))); + + } + + @Test + public void testLogs() throws DockerException, IOException { + + String snippet = "hello world"; + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] {"/bin/echo", snippet}); + + ContainerCreateResponse container = dockerClient.createContainer(containerConfig); + LOG.info("Created container " + container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); + + int exitCode = dockerClient.waitContainer(container.getId()); + + assertThat(exitCode, equalTo(0)); + + 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, equalTo(snippet)); + } + + @Test + public void testDiff() throws DockerException { + 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()); + boolean add = tmpContainers.add(container.getId()); + int exitCode = dockerClient.waitContainer(container.getId()); + assertThat(exitCode, equalTo(0)); + + List filesystemDiff = dockerClient.containterDiff(container.getId()); + LOG.info("Container DIFF: " + filesystemDiff.toString()); + + assertThat(filesystemDiff.size(), equalTo(4)); + ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); + + assertThat(testChangeLog, hasField("path", equalTo("/test"))); + assertThat(testChangeLog, hasField("kind", equalTo(1))); + } + + @Test + public void testStopContainer() throws DockerException { + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] {"sleep", "9999"}); + + 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("Stopping container " + container.getId()); + dockerClient.stopContainer(container.getId(), 2); + + ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); + LOG.info("Container Inspect:" + containerInspectResponse.toString()); + + assertThat(containerInspectResponse.getState().running, is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); + } + + @Test + public void testKillContainer() throws DockerException { + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] {"sleep", "9999"}); + + 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("Killing container " + container.getId()); + dockerClient.kill(container.getId()); + + ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); + LOG.info("Container Inspect:" + containerInspectResponse.toString()); + + assertThat(containerInspectResponse.getState().running, is(equalTo(false))); + assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); + + } + + @Test + public void restartContainer() throws DockerException { + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] {"sleep", "9999"}); + + ContainerCreateResponse container = dockerClient.createContainer(containerConfig); + LOG.info("Created container " + container.toString()); + assertThat(container.getId(), not(isEmptyString())); + dockerClient.startContainer(container.getId()); + tmpContainers.add(container.getId()); + + ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); + LOG.info("Container Inspect:" + containerInspectResponse.toString()); + + String startTime = containerInspectResponse.getState().startedAt; + + dockerClient.restart(container.getId(), 2); + + ContainerInspectResponse containerInspectResponse2 = dockerClient.inspectContainer(container.getId()); + LOG.info("Container Inspect After Restart:" + containerInspectResponse2.toString()); + + String startTime2 = containerInspectResponse2.getState().startedAt; + + assertThat(startTime, not(equalTo(startTime2))); + + assertThat(containerInspectResponse.getState().running, is(equalTo(true))); + + dockerClient.kill(container.getId()); + } + + @Test + public void removeContainer() throws DockerException { + + ContainerConfig containerConfig = new ContainerConfig(); + containerConfig.setImage("busybox"); + containerConfig.setCmd(new String[] {"true"}); + + ContainerCreateResponse container = dockerClient.createContainer(containerConfig); + + dockerClient.startContainer(container.getId()); + dockerClient.waitContainer(container.getId()); + tmpContainers.add(container.getId()); + + LOG.info("Removing container " + container.getId()); + dockerClient.removeContainer(container.getId()); + + List containers2 = dockerClient.listContainers(true); + Matcher matcher = not(hasItem(hasField("id", startsWith(container.getId())))); + assertThat(containers2, matcher); + + } + + /* + * ################## + * ## IMAGES TESTS ## + * ################## + * */ + + @Test + public void testPullImage() throws DockerException, IOException { + + String testImage = "joffrey/test001"; + + LOG.info("Removing image " + testImage); + dockerClient.removeImage(testImage); + + Info info = dockerClient.info(); + LOG.info("Client info " + info.toString()); + + int imgCount= info.getImages(); + + LOG.info("Pulling image " + 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("Pulling repository joffrey/test001")); + + tmpImgs.add(testImage); + + info = dockerClient.info(); + LOG.info("Client info after pull " + info.toString()); + + assertThat(imgCount + 2, equalTo(info.getImages())); + + ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(testImage); + LOG.info("Image Inspect: " + imageInspectResponse.toString()); + assertThat(imageInspectResponse, notNullValue()); + } + + + @Test + public void commitImage() throws DockerException { + + 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.Builder(container.getId()).build()); + 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 { + + + 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.Builder(container.getId()).build()); + tmpImgs.add(imageId); + + 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 testNgixDockerfileBuilder() 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.substringAfterLast(fullLog, "Successfully built ").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.substringAfterLast(fullLog, "Successfully built ").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().portMapping, notNullValue()); + int port = Integer.valueOf(containerInspectResponse.getNetworkSettings().portMapping.get("Tcp").get("6900")); + + + LOG.info("Checking port {} is open", port); + assertThat(available(port), is(false)); + + dockerClient.stopContainer(container.getId(), 0); + + LOG.info("Checking port {} is closed", port); + assertThat(available(port), is(true)); + + } + + + // 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.substringAfterLast(fullLog, "Successfully built ").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(), equalTo(expectedText)); + } } \ No newline at end of file From 330beb790800d39108e9f9e56d260f32e231d50e Mon Sep 17 00:00:00 2001 From: Dusan Katona Date: Sun, 19 Jan 2014 14:05:34 +0100 Subject: [PATCH 05/72] Added method for setting container name during container creation --- .../com/kpelykh/docker/client/DockerClient.java | 13 +++++++++++-- 1 file changed, 11 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 46524aa5..4c8fd510 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -313,10 +313,19 @@ public List listContainers(boolean allContainers, boolean latest, int return containers; } + public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException{ + return createContainer(config, null); + } + + public ContainerCreateResponse createContainer(ContainerConfig config, String name) throws DockerException { - public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException { + String url = restEndpointUrl + "/containers/create"; + + if (!StringUtils.isEmpty(name)){ + url = url + "?name=" + name; + } - WebResource webResource = client.resource(restEndpointUrl + "/containers/create"); + WebResource webResource = client.resource(url); try { LOGGER.trace("POST: " + webResource.toString()); From 5f5a100d928bf6b9146294feaee55ed0ae06d62d Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 31 Jan 2014 17:15:58 +0100 Subject: [PATCH 06/72] make local docker URL configurable --- .../com/kpelykh/docker/client/test/DockerClientTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 17b0900b..4b750039 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -44,9 +44,10 @@ public class DockerClientTest extends Assert @BeforeTest public void beforeTest() throws DockerException { + String url = System.getProperty("docker.url", "http://localhost:4243"); LOG.info("======================= BEFORETEST ======================="); - LOG.info("Connecting to Docker server at http://localhost:4243"); - dockerClient = new DockerClient("http://172.16.2.150:7979"); + LOG.info("Connecting to Docker server at " + url); + dockerClient = new DockerClient(url); LOG.info("Creating image 'busybox'"); dockerClient.pull("busybox"); From 96d91a5e343b6212b1773d67323be1d1cfd15dc1 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 31 Jan 2014 17:20:38 +0100 Subject: [PATCH 07/72] compile with java 6 --- src/main/java/com/kpelykh/docker/client/model/Ports.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 fee9d5be..e012e0f1 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Ports.java +++ b/src/main/java/com/kpelykh/docker/client/model/Ports.java @@ -18,7 +18,7 @@ */ @JsonDeserialize(using=Ports.Deserializer.class) public class Ports { - private final Map ports = new HashMap<>(); + private final Map ports = new HashMap(); private Port[] mapping; private Ports() { } From d1ff671fee89e417ca8de39eac554015668e24f2 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 31 Jan 2014 17:23:02 +0100 Subject: [PATCH 08/72] uncomment, or tests don't even compile --- .../kpelykh/docker/client/model/ContainerInspectResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 acf92e98..e194e686 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -154,7 +154,7 @@ public class NetworkSettings { @JsonProperty("Gateway") public String gateway; @JsonProperty("Bridge") public String bridge; // Deprecated - can we remove? -// @JsonProperty("PortMapping") public Map> portMapping; + @JsonProperty("PortMapping") public Map> portMapping; // FIXME Is this the right type? -BJE @JsonProperty("Ports") public Map ports; From dfc7505e3301ac38a54d7a608b7cb525547a77e3 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Sat, 1 Feb 2014 11:00:18 +0100 Subject: [PATCH 09/72] typo in test name --- .../java/com/kpelykh/docker/client/test/DockerClientTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4b750039..66d5bfa1 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -579,7 +579,7 @@ public void testRunShlex() throws DockerException { @Test - public void testNgixDockerfileBuilder() throws DockerException, IOException { + public void testNginxDockerfileBuilder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); ClientResponse response = dockerClient.build(baseDir); From 76c86f4a912858020360f9b7c51d395a3fd9e55c Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Sat, 1 Feb 2014 11:11:58 +0100 Subject: [PATCH 10/72] misuse of slf4j API --- .../kpelykh/docker/client/DockerClient.java | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 46524aa5..f8e914c2 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -79,7 +79,7 @@ public Info info() throws DockerException { // webResource.addFilter(new com.sun.jersey.api.client.filter.LoggingFilter()); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON).get(Info.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 500) { @@ -95,7 +95,7 @@ public Version version() throws DockerException { WebResource webResource = client.resource(restEndpointUrl + "/version"); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON).get(Version.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 500) { @@ -138,7 +138,7 @@ public ClientResponse pull(String repository, String tag, String registry) throw WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 500) { @@ -168,14 +168,14 @@ public void removeImage(String imageId) throws DockerException { try { WebResource webResource = client.resource(restEndpointUrl + "/images/" + imageId); - LOGGER.trace("DELETE: " + webResource.toString()); + 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(String.format("%s no such image", imageId)); + LOGGER.warn("{} no such image", imageId); } else if (exception.getResponse().getStatus() == 409) { throw new DockerException("Conflict"); } else if (exception.getResponse().getStatus() == 500) { @@ -199,9 +199,9 @@ public String getVizImages() throws DockerException { WebResource webResource = client.resource(restEndpointUrl + "/images/viz"); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); String response = webResource.get(String.class); - LOGGER.trace("Response:" + response.toString()); + LOGGER.trace("Response: {}", response); return response; } catch (UniformInterfaceException exception) { @@ -237,9 +237,9 @@ public List getImages(String name, boolean allImages) throws DockerExcept WebResource webResource = client.resource(restEndpointUrl + "/images/json").queryParams(params); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); List images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response:" + images.toString()); + LOGGER.trace("Response: {}", images); return images; } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 400) { @@ -258,7 +258,7 @@ public ImageInspectResponse inspectImage(String imageId) throws DockerException WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { @@ -306,9 +306,9 @@ public List listContainers(boolean allContainers, boolean latest, int params.add("size", showSize ? "1" : "0"); WebResource webResource = client.resource(restEndpointUrl + "/containers/json").queryParams(params); - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); List containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); - LOGGER.trace("Response:" + containers.toString()); + LOGGER.trace("Response: {}", containers); return containers; } @@ -319,7 +319,7 @@ public ContainerCreateResponse createContainer(ContainerConfig config) throws Do WebResource webResource = client.resource(restEndpointUrl + "/containers/create"); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON) .post(ContainerCreateResponse.class, config); @@ -346,7 +346,7 @@ public void startContainer(String containerId, HostConfig hostConfig) throws Doc WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); Builder builder = webResource.accept(MediaType.TEXT_PLAIN); if (hostConfig != null) { builder.type(MediaType.APPLICATION_JSON).post(hostConfig); @@ -358,7 +358,7 @@ public void startContainer(String containerId, HostConfig hostConfig) throws Doc throw new DockerException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 204) { //no error - LOGGER.trace("Successfully started container " + containerId); + LOGGER.trace("Successfully started container {}", containerId); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -372,7 +372,7 @@ public ContainerInspectResponse inspectContainer(String containerId) throws Dock WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { @@ -396,9 +396,9 @@ public void removeContainer(String containerId, boolean removeVolumes) throws Do WebResource webResource = client.resource(restEndpointUrl + "/containers/" + containerId).queryParam("v", removeVolumes ? "1" : "0"); try { - LOGGER.trace("DELETE: " + webResource.toString()); + LOGGER.trace("DELETE: {}", webResource); String response = webResource.accept(MediaType.APPLICATION_JSON).delete(String.class); - LOGGER.trace("Response:" + response); + LOGGER.trace("Response: {}", response); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 204) { //no error @@ -428,7 +428,7 @@ public int waitContainer(String containerId) throws DockerException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); try { - LOGGER.trace("POST: " + webResource.toString()); + 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) { @@ -466,7 +466,7 @@ private ClientResponse logContainer(String containerId, boolean stream) throws D .queryParams(params); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class, params); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 400) { @@ -486,7 +486,7 @@ public List containterDiff(String containerId) throws DockerException WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); try { - LOGGER.trace("GET: " + webResource.toString()); + LOGGER.trace("GET: {}", webResource); return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { @@ -513,14 +513,14 @@ public void stopContainer(String containerId, int timeout) throws DockerExceptio try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - LOGGER.warn(String.format("No such container %s", containerId)); + LOGGER.warn("No such container {}", containerId); } else if (exception.getResponse().getStatus() == 204) { //no error - LOGGER.trace("Successfully stopped container " + containerId); + LOGGER.trace("Successfully stopped container {}", containerId); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -533,14 +533,14 @@ public void kill(String containerId) throws DockerException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/kill", containerId)); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - LOGGER.warn(String.format("No such container %s", containerId)); + LOGGER.warn("No such container {}", containerId); } else if (exception.getResponse().getStatus() == 204) { //no error - LOGGER.trace("Successfully killed container " + containerId); + LOGGER.trace("Successfully killed container {}", containerId); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -553,14 +553,14 @@ public void restart(String containerId, int timeout) throws DockerException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { throw new DockerException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 204) { //no error - LOGGER.trace("Successfully restarted container " + containerId); + LOGGER.trace("Successfully restarted container {}", containerId); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -583,7 +583,7 @@ public String commit(CommitConfig commitConfig) throws DockerException { WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); JSONObject jsonObject = webResource.accept("application/vnd.docker.raw-stream").post(JSONObject.class, params); return jsonObject.getString("Id"); } catch (UniformInterfaceException exception) { @@ -668,7 +668,7 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio WebResource webResource = client.resource(restEndpointUrl + "/build").queryParams(params); try { - LOGGER.trace("POST: " + webResource.toString()); + LOGGER.trace("POST: {}", webResource); return webResource .type("application/tar") .accept(MediaType.TEXT_PLAIN) From b7499a4105834a7c8b335bd6353b75553a83992f Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Sat, 1 Feb 2014 11:01:03 +0100 Subject: [PATCH 11/72] fluent-builder style setters --- .../docker/client/model/CommitConfig.java | 29 ++++++++ .../docker/client/model/ContainerConfig.java | 66 ++++++++++++------- .../docker/client/model/HostConfig.java | 23 +++++-- 3 files changed, 91 insertions(+), 27 deletions(-) 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 dc5c2c2f..db53904d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java @@ -53,6 +53,35 @@ public String getRun() { return run; } + public CommitConfig setRepo(String repo) { + this.repo = repo; + return this; + } + + public CommitConfig setTag(String tag) { + this.tag = tag; + return this; + } + + public CommitConfig setMessage(String message) { + this.message = message; + return this; + } + + public CommitConfig setAuthor(String author) { + this.author = author; + return this; + } + + public CommitConfig setRun(String run) { + this.run = run; + return this; + } + + public CommitConfig(String container) { + this.container = container; + } + private CommitConfig(Builder b) { this.container = b.container; this.repo = b.repo; 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 df6c5ee0..ff7ffc4e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -52,172 +52,194 @@ public String getDomainName() { public String getWorkingDir() { return workingDir; } - public void setWorkingDir(String workingDir) { + public ContainerConfig setWorkingDir(String workingDir) { this.workingDir = workingDir; + return this; } public boolean isPrivileged() { return privileged; } - public void setPrivileged(boolean privileged) { + public ContainerConfig setPrivileged(boolean privileged) { this.privileged = privileged; + return this; } public String getHostName() { return hostName; } - public void setNetworkDisabled(boolean networkDisabled) { + public ContainerConfig setNetworkDisabled(boolean networkDisabled) { this.networkDisabled = networkDisabled; + return this; } - public void setHostName(String hostName) { + public ContainerConfig setHostName(String hostName) { this.hostName = hostName; + return this; } public String[] getPortSpecs() { return portSpecs; } - public void setPortSpecs(String[] portSpecs) { + public ContainerConfig setPortSpecs(String[] portSpecs) { this.portSpecs = portSpecs; + return this; } public String getUser() { return user; } - public void setUser(String user) { + public ContainerConfig setUser(String user) { this.user = user; + return this; } public boolean isTty() { return tty; } - public void setTty(boolean tty) { + public ContainerConfig setTty(boolean tty) { this.tty = tty; + return this; } public boolean isStdinOpen() { return stdinOpen; } - public void setStdinOpen(boolean stdinOpen) { + public ContainerConfig setStdinOpen(boolean stdinOpen) { this.stdinOpen = stdinOpen; + return this; } public boolean isStdInOnce() { return stdInOnce; } - public void setStdInOnce(boolean stdInOnce) { + public ContainerConfig setStdInOnce(boolean stdInOnce) { this.stdInOnce = stdInOnce; + return this; } public long getMemoryLimit() { return memoryLimit; } - public void setMemoryLimit(long memoryLimit) { + public ContainerConfig setMemoryLimit(long memoryLimit) { this.memoryLimit = memoryLimit; + return this; } public long getMemorySwap() { return memorySwap; } - public void setMemorySwap(long memorySwap) { + public ContainerConfig setMemorySwap(long memorySwap) { this.memorySwap = memorySwap; + return this; } public int getCpuShares() { return cpuShares; } - public void setCpuShares(int cpuShares) { + public ContainerConfig setCpuShares(int cpuShares) { this.cpuShares = cpuShares; + return this; } public boolean isAttachStdin() { return attachStdin; } - public void setAttachStdin(boolean attachStdin) { + public ContainerConfig setAttachStdin(boolean attachStdin) { this.attachStdin = attachStdin; + return this; } public boolean isAttachStdout() { return attachStdout; } - public void setAttachStdout(boolean attachStdout) { + public ContainerConfig setAttachStdout(boolean attachStdout) { this.attachStdout = attachStdout; + return this; } public boolean isAttachStderr() { return attachStderr; } - public void setAttachStderr(boolean attachStderr) { + public ContainerConfig setAttachStderr(boolean attachStderr) { this.attachStderr = attachStderr; + return this; } public String[] getEnv() { return env; } - public void setEnv(String[] env) { + public ContainerConfig setEnv(String[] env) { this.env = env; + return this; } public String[] getCmd() { return cmd; } - public void setCmd(String[] cmd) { + public ContainerConfig setCmd(String[] cmd) { this.cmd = cmd; + return this; } public String[] getDns() { return dns; } - public void setDns(String[] dns) { + public ContainerConfig setDns(String[] dns) { this.dns = dns; + return this; } public String getImage() { return image; } - public void setImage(String image) { + public ContainerConfig setImage(String image) { this.image = image; + return this; } public Object getVolumes() { return volumes; } - public void setVolumes(Object volumes) { + public ContainerConfig setVolumes(Object volumes) { this.volumes = volumes; + return this; } public String getVolumesFrom() { return volumesFrom; } - public void setVolumesFrom(String volumesFrom) { + public ContainerConfig setVolumesFrom(String volumesFrom) { this.volumesFrom = volumesFrom; + return this; } public String[] getEntrypoint() { return entrypoint; } - public void setEntrypoint(String[] entrypoint) { + public ContainerConfig setEntrypoint(String[] entrypoint) { this.entrypoint = entrypoint; + return this; } @Override 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 45fee6e7..cf0fa18a 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -26,24 +26,27 @@ public String[] getBinds() { return binds; } - public void setBinds(String[] binds) { + public HostConfig setBinds(String[] binds) { this.binds = binds; + return this; } public String getContainerIDFile() { return containerIDFile; } - public void setContainerIDFile(String containerIDFile) { + public HostConfig setContainerIDFile(String containerIDFile) { this.containerIDFile = containerIDFile; + return this; } public LxcConf[] getLxcConf() { return lxcConf; } - public void setLxcConf(LxcConf[] lxcConf) { + public HostConfig setLxcConf(LxcConf[] lxcConf) { this.lxcConf = lxcConf; + return this; } public class LxcConf { @@ -53,20 +56,30 @@ public class LxcConf { @JsonProperty("Value") public String value; + public LxcConf(String key, String value) { + this.key = key; + this.value = value; + } + + public LxcConf() { + } + public String getKey() { return key; } - public void setKey(String key) { + public LxcConf setKey(String key) { this.key = key; + return this; } public String getValue() { return value; } - public void setValue(String value) { + public LxcConf setValue(String value) { this.value = value; + return this; } } From 061907880a3d04509e810c4b9afcb8e637809162 Mon Sep 17 00:00:00 2001 From: Vojtech Juranek Date: Sun, 2 Feb 2014 22:01:02 +0100 Subject: [PATCH 12/72] Update Info and Version model --- src/main/java/com/kpelykh/docker/client/model/Info.java | 8 ++++++++ .../java/com/kpelykh/docker/client/model/Version.java | 8 ++++++++ 2 files changed, 16 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 a38b73c0..ad1e347f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -50,6 +50,9 @@ public class Info { @JsonProperty("NGoroutines") private int NGoroutines; + + @JsonProperty("SwapLimit") + private int swapLimit; public boolean isDebug() { return debug; @@ -102,6 +105,10 @@ public int getNFd() { public int getNGoroutines() { return NGoroutines; } + + public int getSwapLimit() { + return swapLimit; + } @Override public String toString() { @@ -112,6 +119,7 @@ public String toString() { ", NFd=" + NFd + ", NGoroutines=" + NGoroutines + ", memoryLimit=" + memoryLimit + + ", swapLimit=" + swapLimit + ", lxcVersion='" + lxcVersion + '\'' + ", nEventListener=" + nEventListener + ", kernelVersion='" + kernelVersion + '\'' + 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 b81f0953..5f810171 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -18,6 +18,9 @@ public class Version { @JsonProperty("GoVersion") private String goVersion; + + @JsonProperty("KernelVersion") + private String kernelVersion; public String getVersion() { return version; @@ -31,12 +34,17 @@ public String getGoVersion() { return goVersion; } + public String getKernelVersion() { + return kernelVersion; + } + @Override public String toString() { return "Version{" + "version='" + version + '\'' + ", gitCommit='" + gitCommit + '\'' + ", goVersion='" + goVersion + '\'' + + ", kernelVersion='" + kernelVersion + '\'' + '}'; } From f7593aa8165498ed692ff2803364532261cf5b14 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Tue, 4 Feb 2014 17:03:46 -0800 Subject: [PATCH 13/72] updated docker-java to Docker Client API v1.8, Docker Server version 0.7.6 Merged multiple contributions from other forks --- README.md | 55 +++--- pom.xml | 13 +- .../com/google/common/base/Preconditions.java | 25 ++- .../kpelykh/docker/client/DockerClient.java | 38 ++-- .../client/UnixSocketClientHandler.java | 2 +- .../docker/client/model/CommitConfig.java | 51 ------ .../docker/client/model/Container.java | 25 ++- .../model/ContainerInspectResponse.java | 136 ++++++++++----- .../docker/client/model/HostConfig.java | 74 +++++++- .../kpelykh/docker/client/model/Image.java | 66 ++++++- .../client/model/ImageInspectResponse.java | 55 ++++++ .../com/kpelykh/docker/client/model/Info.java | 101 ++++++++++- .../com/kpelykh/docker/client/model/Port.java | 52 ++++++ .../kpelykh/docker/client/model/Ports.java | 82 +++++++-- .../kpelykh/docker/client/model/Version.java | 46 ++++- .../docker/client/test/DockerClientTest.java | 163 ++++++++++-------- 16 files changed, 704 insertions(+), 280 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/model/Port.java diff --git a/README.md b/README.md index 8df21630..2219c66a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") -Supports Docker Client API v1.3, Docker Server version 0.6.1 +Supports a subset of the Docker Client API v1.8, Docker Server version 0.7.6 ## Build with Maven @@ -12,52 +12,53 @@ Supports Docker Client API v1.3, Docker Server version 0.6.1 * 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. -By default maven will run tests during build process. Tests are using localhost instance of Docker, make sure that -you have Docker running, or the tests. +If you don't have Docker running locally, you can skip tests with -DskipTests flag set to true: + + $ mvn clean install -DskipTests=true -*Since version 0.6, Docker is using unix socket for communication, however java client works over TCP/IP, so you need to -make sure that your Docker server is listening on TCP/IP port.* -Run docker: +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 - $ sudo docker -H=tcp://127.0.0.1:4243 -d + DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock" -Make sure that docker is up: +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.6.1 - Server version: 0.6.1 - Git commit: 5105263 - Go version: go1.1.2 - Last stable version: 0.6.1 + $ docker -H tcp://127.0.0.1:4243 version + + Client version: 0.7.6 + Go version (client): go1.2 + Git commit (client): bc3b2ec + Server version: 0.7.6 + Git commit (server): bc3b2ec + Go version (server): go1.2 + Last stable version: 0.7.6 Run build with tests: $ mvn clean install -If you don't have Docker running localy, you can skip tests with -DskipTests flag set to true: - - $ mvn clean install -DskipTests=true - ## Docker Java Client usage: -To use Java Docker client, include dependency into your pom.xml: +docker-java is vailable though Maven Central, so you can include the following dependency into your pom.xml: com.kpelykh docker-java - 0.6.1-SNAPSHOT + 0.7.6 -*Currently Docker Java client is not available in Maven Central, so you will need to install it to a local -repository, before you can use it in your projects.* - + ## Example code snippets: DockerClient dockerClient = new DockerClient("http://localhost:4243"); - ###### Get Docker info: Info info = dockerClient.info(); @@ -81,7 +82,11 @@ repository, before you can use it in your projects.* 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/, diff --git a/pom.xml b/pom.xml index 392bc3b2..7e24e77e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.kpelykh docker-java jar - 0.6.1-SNAPSHOT + 0.7.6-SNAPSHOT docker-java https://github.com/kpelykh/docker-java @@ -48,7 +48,7 @@ 1.6.1 - 1.17.1 + 1.18 1.9 4.2.5 @@ -136,15 +136,6 @@ ${slf4j-api.version} - - - com.google.code.findbugs - jsr305 - true - ${jsr305.version} - - - ch.qos.logback diff --git a/src/main/java/com/google/common/base/Preconditions.java b/src/main/java/com/google/common/base/Preconditions.java index e8632149..6a15fb4d 100644 --- a/src/main/java/com/google/common/base/Preconditions.java +++ b/src/main/java/com/google/common/base/Preconditions.java @@ -17,7 +17,6 @@ package com.google.common.base; -import javax.annotation.Nullable; import java.util.NoSuchElementException; /** @@ -83,7 +82,7 @@ public static void checkArgument(boolean expression) { * @throws IllegalArgumentException if {@code expression} is false */ public static void checkArgument( - boolean expression, @Nullable Object errorMessage) { + boolean expression, Object errorMessage) { if (!expression) { throw new IllegalArgumentException(String.valueOf(errorMessage)); } @@ -109,8 +108,8 @@ public static void checkArgument( * this happen) */ public static void checkArgument(boolean expression, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { + String errorMessageTemplate, + Object... errorMessageArgs) { if (!expression) { throw new IllegalArgumentException( format(errorMessageTemplate, errorMessageArgs)); @@ -140,7 +139,7 @@ public static void checkState(boolean expression) { * @throws IllegalStateException if {@code expression} is false */ public static void checkState( - boolean expression, @Nullable Object errorMessage) { + boolean expression, Object errorMessage) { if (!expression) { throw new IllegalStateException(String.valueOf(errorMessage)); } @@ -166,8 +165,8 @@ public static void checkState( * this happen) */ public static void checkState(boolean expression, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { + String errorMessageTemplate, + Object... errorMessageArgs) { if (!expression) { throw new IllegalStateException( format(errorMessageTemplate, errorMessageArgs)); @@ -199,7 +198,7 @@ public static T checkNotNull(T reference) { * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ - public static T checkNotNull(T reference, @Nullable Object errorMessage) { + public static T checkNotNull(T reference, Object errorMessage) { if (reference == null) { throw new NullPointerException(String.valueOf(errorMessage)); } @@ -224,8 +223,8 @@ public static T checkNotNull(T reference, @Nullable Object errorMessage) { * @throws NullPointerException if {@code reference} is null */ public static T checkNotNull(T reference, - @Nullable String errorMessageTemplate, - @Nullable Object... errorMessageArgs) { + String errorMessageTemplate, + Object... errorMessageArgs) { if (reference == null) { // If either of these parameters is null, the right thing happens anyway throw new NullPointerException( @@ -295,7 +294,7 @@ public static int checkElementIndex(int index, int size) { * @throws IllegalArgumentException if {@code size} is negative */ public static int checkElementIndex( - int index, int size, @Nullable String desc) { + int index, int size, String desc) { // Carefully optimized for execution by hotspot (explanatory comment above) if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); @@ -345,7 +344,7 @@ public static int checkPositionIndex(int index, int size) { * @throws IllegalArgumentException if {@code size} is negative */ public static int checkPositionIndex( - int index, int size, @Nullable String desc) { + int index, int size, String desc) { // Carefully optimized for execution by hotspot (explanatory comment above) if (index < 0 || index > size) { throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); @@ -409,7 +408,7 @@ private static String badPositionIndexes(int start, int end, int size) { * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. Arguments can be null. */ - static String format(String template, @Nullable Object... args) { + static String format(String template, Object... args) { template = String.valueOf(template); // null -> "null" // start substituting the arguments into the '%s' placeholders diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 9814b82d..103713d6 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -48,7 +48,7 @@ public class DockerClient private String restEndpointUrl; public DockerClient(String serverUrl) { - restEndpointUrl = serverUrl + "/v1.3"; + restEndpointUrl = serverUrl + "/v1.8"; ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); @@ -61,9 +61,11 @@ public DockerClient(String serverUrl) { // Increase default max connection per route cm.setDefaultMaxPerRoute(1000); - // HttpClient httpClient = new DefaultHttpClient(cm); - //client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig); - client = new UnixSocketClient(clientConfig); + 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()); @@ -316,21 +318,19 @@ public ContainerCreateResponse createContainer(ContainerConfig config) throws Do return createContainer(config, null); } - public ContainerCreateResponse createContainer(ContainerConfig config, String name) throws DockerException { - - String url = restEndpointUrl + "/containers/create"; + public ContainerCreateResponse createContainer(ContainerConfig config,String name) throws DockerException { - if (!StringUtils.isEmpty(name)){ - url = url + "?name=" + name; + MultivaluedMap params = new MultivaluedMapImpl(); + if(name != null){ + params.add("name", name); } - - WebResource webResource = client.resource(url); + WebResource webResource = client.resource(restEndpointUrl + "/containers/create").queryParams(params); try { - LOGGER.trace("POST: {}", webResource); + LOGGER.trace("POST: {} ", webResource); return webResource.accept(MediaType.APPLICATION_JSON) - .type(MediaType.APPLICATION_JSON) - .post(ContainerCreateResponse.class, config); + .type(MediaType.APPLICATION_JSON) + .post(ContainerCreateResponse.class, config); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { throw new DockerException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage())); @@ -643,20 +643,20 @@ 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.startsWith(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.isAbsolute()) { + src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); } if (!src.exists()) { - throw new DockerException(String.format("Sorce file %s doesnt' exist", src)); - } + throw new DockerException(String.format("Sorce file %s doesnt' exist", src)); + }*/ if (src.isDirectory()) { FileUtils.copyDirectory(src, tmpDockerContextFolder); } else { diff --git a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java index 3b1ef752..6ce3f1ce 100644 --- a/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java +++ b/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java @@ -10,6 +10,7 @@ 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; @@ -22,7 +23,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.concurrent.NotThreadSafe; import java.io.*; import java.net.URI; import java.nio.channels.Channels; 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 db53904d..69af9959 100644 --- a/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java @@ -82,55 +82,4 @@ public CommitConfig(String container) { this.container = container; } - private CommitConfig(Builder b) { - this.container = b.container; - this.repo = b.repo; - this.tag = b.tag; - this.message = b.message; - this.author = b.author; - this.run = b.run; - } - - public static class Builder implements IBuilder { - private String container; - private String repo; - private String tag; - private String message; - private String author; - private String run; - - public Builder(String containerId) { - this.container = containerId; - } - - public Builder repo(String repo) { - this.repo = repo; - return this; - } - - public Builder tag(String tag) { - this.tag = tag; - return this; - } - - public Builder message(String message) { - this.message = message; - return this; - } - - public Builder author(String author) { - this.author = author; - return this; - } - - public Builder run(String run) { - this.run = run; - return this; - } - - public CommitConfig build() { - return new CommitConfig(this); - } - } - } 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 bf1e9a14..c9de7434 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Container.java +++ b/src/main/java/com/kpelykh/docker/client/model/Container.java @@ -1,12 +1,16 @@ package com.kpelykh.docker.client.model; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; +import java.util.Arrays; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonIgnoreProperties(ignoreUnknown=true) public class Container { @JsonProperty("Id") @@ -24,8 +28,19 @@ public class Container { @JsonProperty("Status") private String status; - @JsonProperty("Ports") - private String ports; //Example value "49164->6900, 49165->7100" + /* Example: + "Ports": { + "22/tcp": [ + { + "HostIp": "0.0.0.0", + "HostPort": "8022" + } + ] + } + */ + + @JsonProperty("Ports") + public Ports ports; @JsonProperty("SizeRw") private int size; @@ -53,10 +68,14 @@ public String getStatus() { return status; } - public String getPorts() { + public Ports getPorts() { return ports; } + public void setPorts(Ports ports) { + this.ports = ports; + } + public int getSize() { return size; } 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 e194e686..04d2f8c9 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java @@ -61,90 +61,143 @@ public class ContainerInspectResponse { @JsonProperty("Driver") private String driver; - public String getDriver() { - return driver; - } - - public String getHostnamePath() { - return hostnamePath; - } - - public String getHostsPath() { - return hostsPath; - } - - public String getName() { - return name; - } + @JsonProperty("HostConfig") + private HostConfig hostConfig; public String getId() { return id; } + public void setId(String id) { + this.id = id; + } + public String getCreated() { return created; } + public void setCreated(String created) { + this.created = created; + } + public String getPath() { return path; } + public void setPath(String path) { + this.path = path; + } + public String[] getArgs() { return args; } + public void setArgs(String[] args) { + this.args = args; + } + public ContainerConfig getConfig() { return config; } + public void setConfig(ContainerConfig config) { + this.config = config; + } + public ContainerState getState() { return state; } + public void setState(ContainerState state) { + this.state = state; + } + public String getImage() { return image; } + public void setImage(String image) { + this.image = image; + } + public NetworkSettings getNetworkSettings() { return networkSettings; } + public void setNetworkSettings(NetworkSettings networkSettings) { + this.networkSettings = networkSettings; + } + public String getSysInitPath() { return sysInitPath; } + public void setSysInitPath(String sysInitPath) { + this.sysInitPath = sysInitPath; + } + public String getResolvConfPath() { return resolvConfPath; } + public void setResolvConfPath(String resolvConfPath) { + this.resolvConfPath = resolvConfPath; + } + public Map getVolumes() { return volumes; } + public void setVolumes(Map volumes) { + this.volumes = volumes; + } + public Map getVolumesRW() { return volumesRW; } - @Override - public String toString() { - return "ContainerInspectResponse{" + - "id='" + id + '\'' + - ", created='" + created + '\'' + - ", path='" + path + '\'' + - ", args=" + Arrays.toString(args) + - ", config=" + config + - ", state=" + state + - ", image='" + image + '\'' + - ", networkSettings=" + networkSettings + - ", sysInitPath='" + sysInitPath + '\'' + - ", resolvConfPath='" + resolvConfPath + '\'' + - ", volumes=" + volumes + - ", volumesRW=" + volumesRW + - ", hostnamePath='" + hostnamePath + '\'' + - ", hostsPath='" + hostsPath + '\'' + - ", name='" + name + '\'' + - ", driver='" + driver + '\'' + - '}'; + public void setVolumesRW(Map volumesRW) { + this.volumesRW = volumesRW; + } + + public String getHostnamePath() { + return hostnamePath; + } + + public void setHostnamePath(String hostnamePath) { + this.hostnamePath = hostnamePath; + } + + public String getHostsPath() { + return hostsPath; + } + + public void setHostsPath(String hostsPath) { + this.hostsPath = hostsPath; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDriver() { + return driver; + } + + public void setDriver(String driver) { + this.driver = driver; + } + + public HostConfig getHostConfig() { + return hostConfig; + } + + public void setHostConfig(HostConfig hostConfig) { + this.hostConfig = hostConfig; } public class NetworkSettings { @@ -153,19 +206,18 @@ public class NetworkSettings { @JsonProperty("IPPrefixLen") public int ipPrefixLen; @JsonProperty("Gateway") public String gateway; @JsonProperty("Bridge") public String bridge; - // Deprecated - can we remove? @JsonProperty("PortMapping") public Map> portMapping; - // FIXME Is this the right type? -BJE - @JsonProperty("Ports") public Map ports; + @JsonProperty("Ports") public Ports ports; @Override public String toString() { return "NetworkSettings{" + - "ipAddress='" + ipAddress + '\'' + - ", ipPrefixLen=" + ipPrefixLen + - ", gateway='" + gateway + '\'' + + "ports=" + ports + + ", portMapping=" + portMapping + ", bridge='" + bridge + '\'' + - ", ports=" + ports + + ", gateway='" + gateway + '\'' + + ", ipPrefixLen=" + ipPrefixLen + + ", ipAddress='" + ipAddress + '\'' + '}'; } } 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 cf0fa18a..e124cf0d 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -2,6 +2,8 @@ import org.codehaus.jackson.annotate.JsonProperty; +import java.util.Arrays; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) @@ -18,35 +20,91 @@ public class HostConfig { @JsonProperty("LxcConf") private LxcConf[] lxcConf; - public HostConfig(String[] binds) { - this.binds = binds; + + @JsonProperty("Links") + private String[] links; + + @JsonProperty("PortBindings") + private Ports portBindings; + + @JsonProperty("Privileged") + private boolean privileged; + + @JsonProperty("PublishAllPorts") + private boolean publishAllPorts; + + public HostConfig() { + this.binds = null; } + public String[] getBinds() { return binds; } - public HostConfig setBinds(String[] binds) { + public void setBinds(String[] binds) { this.binds = binds; - return this; } public String getContainerIDFile() { return containerIDFile; } - public HostConfig setContainerIDFile(String containerIDFile) { + public void setContainerIDFile(String containerIDFile) { this.containerIDFile = containerIDFile; - return this; } public LxcConf[] getLxcConf() { return lxcConf; } - public HostConfig setLxcConf(LxcConf[] lxcConf) { + public void setLxcConf(LxcConf[] lxcConf) { this.lxcConf = lxcConf; - return this; + } + + public String[] getLinks() { + return links; + } + + public void setLinks(String[] links) { + this.links = links; + } + + public Ports getPortBindings() { + return portBindings; + } + + public void setPortBindings(Ports portBindings) { + this.portBindings = portBindings; + } + + public boolean isPrivileged() { + return privileged; + } + + public void setPrivileged(boolean privileged) { + this.privileged = privileged; + } + + public boolean isPublishAllPorts() { + return publishAllPorts; + } + + public void setPublishAllPorts(boolean publishAllPorts) { + this.publishAllPorts = publishAllPorts; + } + + @Override + public String toString() { + return "HostConfig{" + + "binds=" + Arrays.toString(binds) + + ", containerIDFile='" + containerIDFile + '\'' + + ", lxcConf=" + Arrays.toString(lxcConf) + + ", links=" + Arrays.toString(links) + + ", portBindings=" + portBindings + + ", privileged=" + privileged + + ", publishAllPorts=" + publishAllPorts + + '}'; } public class LxcConf { 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 ac0c4a7e..4b68590c 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Image.java +++ b/src/main/java/com/kpelykh/docker/client/model/Image.java @@ -2,6 +2,8 @@ import org.codehaus.jackson.annotate.JsonProperty; +import java.util.Arrays; + /** * * @author Konstantin Pelykh (kpelykh@gmail.com) @@ -9,14 +11,21 @@ */ public class Image { + @JsonProperty("Id") + private String id; + + @JsonProperty("RepoTags") + private String[] repoTags; + @JsonProperty("Repository") private String repository; @JsonProperty("Tag") private String tag; - @JsonProperty("Id") - private String id; + + @JsonProperty("ParentId") + private String parentId; @JsonProperty("Created") private long created; @@ -27,40 +36,81 @@ public class Image { @JsonProperty("VirtualSize") private long virtualSize; + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String[] getRepoTags() { + return repoTags; + } + + public void setRepoTags(String[] repoTags) { + this.repoTags = repoTags; + } + public String getRepository() { return repository; } + public void setRepository(String repository) { + this.repository = repository; + } + public String getTag() { return tag; } - public String getId() { - return id; + public void setTag(String tag) { + this.tag = tag; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; } public long getCreated() { return created; } + public void setCreated(long created) { + this.created = created; + } + public long getSize() { return size; } + public void setSize(long size) { + this.size = size; + } + public long getVirtualSize() { return virtualSize; } + public void setVirtualSize(long virtualSize) { + this.virtualSize = virtualSize; + } + @Override public String toString() { return "Image{" + - "repository='" + repository + '\'' + - ", tag='" + tag + '\'' + + "virtualSize=" + virtualSize + ", id='" + id + '\'' + + ", repoTags=" + Arrays.toString(repoTags) + + ", repository='" + repository + '\'' + + ", tag='" + tag + '\'' + + ", parentId='" + parentId + '\'' + ", created=" + created + ", size=" + size + - ", virtualSize=" + virtualSize + '}'; } - } 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 33c7cfb7..4b714f4f 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java @@ -32,50 +32,104 @@ public class ImageInspectResponse { @JsonProperty("author") private String author; + @JsonProperty("os") private String os; + public String getId() { return id; } + public void setId(String id) { + this.id = id; + } + public String getParent() { return parent; } + public void setParent(String parent) { + this.parent = parent; + } + public String getCreated() { return created; } + public void setCreated(String created) { + this.created = created; + } + public String getContainer() { return container; } + public void setContainer(String container) { + this.container = container; + } + public ContainerConfig getContainerConfig() { return containerConfig; } + public void setContainerConfig(ContainerConfig containerConfig) { + this.containerConfig = containerConfig; + } + public int getSize() { return size; } + public void setSize(int size) { + this.size = size; + } + public String getDockerVersion() { return dockerVersion; } + public void setDockerVersion(String dockerVersion) { + this.dockerVersion = dockerVersion; + } + public ContainerConfig getConfig() { return config; } + public void setConfig(ContainerConfig config) { + this.config = config; + } + public String getArch() { return arch; } + public void setArch(String arch) { + this.arch = arch; + } + public String getComment() { return comment; } + public void setComment(String comment) { + this.comment = comment; + } + public String getAuthor() { return author; } + public void setAuthor(String author) { + this.author = author; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + @Override public String toString() { return "ImageInspectResponse{" + @@ -90,6 +144,7 @@ public String toString() { ", arch='" + arch + '\'' + ", comment='" + comment + '\'' + ", author='" + author + '\'' + + ", os='" + os + '\'' + '}'; } } 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 ad1e347f..30667029 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -1,6 +1,7 @@ package com.kpelykh.docker.client.model; import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonSerialize; import java.util.List; @@ -9,6 +10,7 @@ * @author Konstantin Pelykh (kpelykh@gmail.com) * */ +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public class Info { @JsonProperty("Debug") @@ -33,6 +35,13 @@ public class Info { @JsonProperty("IndexServerAddress") private String IndexServerAddress; + + @JsonProperty("InitPath") + private String initPath; + + @JsonProperty("InitSha1") + private String initSha1; + @JsonProperty("KernelVersion") private String kernelVersion; @@ -58,56 +67,128 @@ public boolean isDebug() { return debug; } + public void setDebug(boolean debug) { + this.debug = debug; + } + public int getContainers() { return containers; } + public void setContainers(int containers) { + this.containers = containers; + } + public String getDriver() { return driver; } + public void setDriver(String driver) { + this.driver = driver; + } + public List getDriverStatuses() { return driverStatuses; } + public void setDriverStatuses(List driverStatuses) { + this.driverStatuses = driverStatuses; + } + public int getImages() { return images; } + public void setImages(int images) { + this.images = images; + } + public String getIPv4Forwarding() { return IPv4Forwarding; } + public void setIPv4Forwarding(String IPv4Forwarding) { + this.IPv4Forwarding = IPv4Forwarding; + } + public String getIndexServerAddress() { return IndexServerAddress; } + public void setIndexServerAddress(String indexServerAddress) { + IndexServerAddress = indexServerAddress; + } + + public String getInitPath() { + return initPath; + } + + public void setInitPath(String initPath) { + this.initPath = initPath; + } + + public String getInitSha1() { + return initSha1; + } + + public void setInitSha1(String initSha1) { + this.initSha1 = initSha1; + } + public String getKernelVersion() { return kernelVersion; } + public void setKernelVersion(String kernelVersion) { + this.kernelVersion = kernelVersion; + } + public String getLxcVersion() { return lxcVersion; } + public void setLxcVersion(String lxcVersion) { + this.lxcVersion = lxcVersion; + } + public boolean isMemoryLimit() { return memoryLimit; } + public void setMemoryLimit(boolean memoryLimit) { + this.memoryLimit = memoryLimit; + } + public long getnEventListener() { return nEventListener; } + public void setnEventListener(long nEventListener) { + this.nEventListener = nEventListener; + } + public int getNFd() { return NFd; } + public void setNFd(int NFd) { + this.NFd = NFd; + } + public int getNGoroutines() { return NGoroutines; } - + + public void setNGoroutines(int NGoroutines) { + this.NGoroutines = NGoroutines; + } + public int getSwapLimit() { - return swapLimit; + return swapLimit; + } + + public void setSwapLimit(int swapLimit) { + this.swapLimit = swapLimit; } @Override @@ -115,16 +196,20 @@ public String toString() { return "Info{" + "debug=" + debug + ", containers=" + containers + + ", driver='" + driver + '\'' + + ", driverStatuses=" + driverStatuses + ", images=" + images + + ", IPv4Forwarding='" + IPv4Forwarding + '\'' + + ", IndexServerAddress='" + IndexServerAddress + '\'' + + ", initPath='" + initPath + '\'' + + ", initSha1='" + initSha1 + '\'' + + ", kernelVersion='" + kernelVersion + '\'' + + ", lxcVersion='" + lxcVersion + '\'' + + ", memoryLimit=" + memoryLimit + + ", nEventListener=" + nEventListener + ", NFd=" + NFd + ", NGoroutines=" + NGoroutines + - ", memoryLimit=" + memoryLimit + ", swapLimit=" + swapLimit + - ", lxcVersion='" + lxcVersion + '\'' + - ", nEventListener=" + nEventListener + - ", kernelVersion='" + kernelVersion + '\'' + - ", IPv4Forwarding='" + IPv4Forwarding + '\'' + - ", IndexServerAddress='" + IndexServerAddress + '\'' + '}'; } } diff --git a/src/main/java/com/kpelykh/docker/client/model/Port.java b/src/main/java/com/kpelykh/docker/client/model/Port.java new file mode 100644 index 00000000..b4fa913a --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/Port.java @@ -0,0 +1,52 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * @author Nicolas De Loof + */ + +public class Port { + + @JsonProperty("PrivatePort") + private long privatePort; + + @JsonProperty("PublicPort") + private long publicPort; + + @JsonProperty("Type") + private String type; + + public long getPrivatePort() { + return privatePort; + } + + public void setPrivatePort(long privatePort) { + this.privatePort = privatePort; + } + + public long getPublicPort() { + return publicPort; + } + + public void setPublicPort(long publicPort) { + this.publicPort = publicPort; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public String toString() { + return "Port{" + + "privatePort=" + privatePort + + ", publicPort=" + publicPort + + ", type='" + type + '\'' + + '}'; + } +} \ No newline at end of file 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 e012e0f1..17f57b6e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Ports.java +++ b/src/main/java/com/kpelykh/docker/client/model/Ports.java @@ -1,12 +1,12 @@ package com.kpelykh.docker.client.model; -import org.codehaus.jackson.JsonNode; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.ObjectCodec; +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 java.io.IOException; import java.util.HashMap; @@ -17,29 +17,39 @@ * Created by ben on 16/12/13. */ @JsonDeserialize(using=Ports.Deserializer.class) +@JsonSerialize(using=Ports.Serializer.class) public class Ports { + + private final Map ports = new HashMap(); - private Port[] mapping; - private Ports() { } + public Ports() { } - private void addPort(Port port) { + public void addPort(Port port) { ports.put(port.getPort(), port); } - private void addMapping(Port src, Port target) { - Port p = ports.get(src); - if (p==null) return; -// p.addMapping(target); + @Override + public String toString(){ + return ports.toString(); + } + + public Map getAllPorts(){ + return ports; } public static class Port{ + private final String scheme; private final String port; + private final String hostIp; + private final String hostPort; - public Port(String scheme_, String port_) { + public Port(String scheme_, String port_, String hostIp_, String hostPort_) { scheme = scheme_; port = port_; + hostIp = hostIp_; + hostPort = hostPort_; } public String getScheme() { @@ -50,10 +60,18 @@ public String getPort() { return port; } - public static Port makePort(String full) { + public String getHostIp() { + return hostIp; + } + + public String getHostPort() { + return hostPort; + } + + public static Port makePort(String full, String hostIp, String hostPort) { if (full == null) return null; String[] pieces = full.split("/"); - return new Port(pieces[1], pieces[0]); + return new Port(pieces[1], pieces[0], hostIp, hostPort); } @Override @@ -61,6 +79,8 @@ public String toString() { return "Port{" + "scheme='" + scheme + '\'' + ", port='" + port + '\'' + + ", hostIp='" + hostIp + '\'' + + ", hostPort='" + hostPort + '\'' + '}'; } } @@ -68,16 +88,42 @@ public String toString() { public static class Deserializer extends JsonDeserializer { @Override public Ports deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + Ports out = new Ports(); ObjectCodec oc = jsonParser.getCodec(); JsonNode node = oc.readTree(jsonParser); - for (Iterator it = node.getFieldNames(); it.hasNext();) { - String pname = it.next(); - out.addPort(Port.makePort(pname)); + for (Iterator> it = node.getFields(); it.hasNext();) { + + Map.Entry field = it.next(); + String hostIp = field.getValue().get(0).get("HostIp").getTextValue(); + String hostPort = field.getValue().get(0).get("HostPort").getTextValue(); + out.addPort(Port.makePort(field.getKey(), hostIp, hostPort)); } return out; } } -} + public static class Serializer extends JsonSerializer { + + @Override + public void serialize(Ports ports, JsonGenerator jsonGen, + SerializerProvider serProvider) throws IOException, JsonProcessingException { + + jsonGen.writeStartObject();//{ + for(String portKey : ports.getAllPorts().keySet()){ + Port p = ports.getAllPorts().get(portKey); + jsonGen.writeFieldName(p.getPort() + "/" + p.getScheme()); + jsonGen.writeStartArray(); + jsonGen.writeStartObject(); + jsonGen.writeStringField("HostIp", p.hostIp); + jsonGen.writeStringField("HostPort", p.hostPort); + jsonGen.writeEndObject(); + jsonGen.writeEndArray(); + } + jsonGen.writeEndObject();//} + } + + } + +} \ No newline at end of file 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 5f810171..915ae67e 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Version.java +++ b/src/main/java/com/kpelykh/docker/client/model/Version.java @@ -22,22 +22,61 @@ public class Version { @JsonProperty("KernelVersion") private String kernelVersion; + @JsonProperty("Arch") + private String arch; + + @JsonProperty("Os") + private String operatingSystem; + + public String getVersion() { return version; } + public void setVersion(String version) { + this.version = version; + } + public String getGitCommit() { return gitCommit; } + public void setGitCommit(String gitCommit) { + this.gitCommit = gitCommit; + } + public String getGoVersion() { return goVersion; } + public void setGoVersion(String goVersion) { + this.goVersion = goVersion; + } + public String getKernelVersion() { - return kernelVersion; + return kernelVersion; } - + + public void setKernelVersion(String kernelVersion) { + this.kernelVersion = kernelVersion; + } + + public String getArch() { + return arch; + } + + public void setArch(String arch) { + this.arch = arch; + } + + public String getOperatingSystem() { + return operatingSystem; + } + + public void setOperatingSystem(String operatingSystem) { + this.operatingSystem = operatingSystem; + } + @Override public String toString() { return "Version{" + @@ -45,7 +84,8 @@ public String toString() { ", gitCommit='" + gitCommit + '\'' + ", goVersion='" + goVersion + '\'' + ", kernelVersion='" + kernelVersion + '\'' + + ", arch='" + arch + '\'' + + ", operatingSystem='" + operatingSystem + '\'' + '}'; } - } 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 3002ffc2..73cbb8bf 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -48,8 +48,8 @@ public void beforeTest() throws DockerException { 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); @@ -68,20 +68,24 @@ public void beforeMethod(Method method) { @AfterMethod public void afterMethod(ITestResult result) { - for (String image : tmpImgs) { - LOG.info("Cleaning up temporary image " + image); + + for (String container : tmpContainers) { + LOG.info("Cleaning up temporary container {}", container); try { - dockerClient.removeImage(image); + dockerClient.stopContainer(container); + dockerClient.kill(container); + dockerClient.removeContainer(container); } catch (DockerException ignore) {} } - for (String container : tmpContainers) { - LOG.info("Cleaning up temporary container " + container); + for (String image : tmpImgs) { + LOG.info("Cleaning up temporary image {}", image); try { - dockerClient.removeContainer(container); + dockerClient.removeImage(image); } catch (DockerException ignore) {} } - LOG.info(String.format("################################## END OF %s ##################################\n", result.getName())); + + LOG.info("################################## END OF {} ##################################\n", result.getName()); } /* @@ -121,7 +125,7 @@ public void testDockerInfo() throws DockerException { @Test public void testDockerSearch() throws DockerException { List dockerSearch = dockerClient.search("busybox"); - LOG.info("Search returned" + dockerSearch.toString()); + LOG.info("Search returned {}", dockerSearch.toString()); Matcher matcher = hasItem(hasField("name", equalTo("busybox"))); assertThat(dockerSearch, matcher); @@ -138,16 +142,15 @@ public void testDockerSearch() throws DockerException { @Test public void testImages() throws DockerException { - List images = dockerClient.getImages(false); + List images = dockerClient.getImages(true); assertThat(images, notNullValue()); - LOG.info("Images List: " + images); + LOG.info("Images List: {}", images); Info info = dockerClient.info(); - //assertThat(images.size(), equalTo(info.images)); + assertThat(images.size(), equalTo(info.getImages())); Image img = images.get(0); assertThat(img.getCreated(), is(greaterThan(0L)) ); - assertThat(img.getSize(), is(greaterThan(0L)) ); assertThat(img.getVirtualSize(), is(greaterThan(0L)) ); assertThat(img.getId(), not(isEmptyString())); assertThat(img.getTag(), not(isEmptyString())); @@ -159,7 +162,7 @@ public void testImages() throws DockerException { public void testListContainers() throws DockerException { List containers = dockerClient.listContainers(true); assertThat(containers, notNullValue()); - LOG.info("Container List: " + containers); + LOG.info("Container List: {}", containers); int size = containers.size(); @@ -201,7 +204,7 @@ public void testCreateContainer() throws DockerException { ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); @@ -216,14 +219,14 @@ public void testStartContainer() throws DockerException { containerConfig.setCmd(new String[]{"true"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + 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()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); assertThat(containerInspectResponse.config, is(notNullValue())); assertThat(containerInspectResponse.getId(), not(isEmptyString())); @@ -241,6 +244,22 @@ public void testStartContainer() throws DockerException { } + /* @Test + public void testStartContainer2() throws DockerException {ContainerConfig appContainerConfig = new ContainerConfig(); + appContainerConfig.setImage("4096e911ada1"); + ContainerCreateResponse appContResponse = dockerClient.createContainer(appContainerConfig, "AppContainer"); + System.out.println("Created an App container successfully: " + appContResponse.getId()); + String appContId = appContResponse.getId(); + HostConfig appHostConfig = new HostConfig(null); + Port p = new Port("tcp","8080","0.0.0.0","8082"); + Ports ports = new Ports(); + ports.addPort(p); + appHostConfig.setPortBindings(ports); + String[] links = {"mariaDB3:db"}; + appHostConfig.setLinks(links); + dockerClient.startContainer(appContId, appHostConfig); + } +*/ @Test public void testWaitContainer() throws DockerException { @@ -249,19 +268,19 @@ public void testWaitContainer() throws DockerException { containerConfig.setCmd(new String[]{"true"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); tmpContainers.add(container.getId()); dockerClient.startContainer(container.getId()); int exitCode = dockerClient.waitContainer(container.getId()); - LOG.info("Container exit code: " + exitCode); + LOG.info("Container exit code: {}", exitCode); assertThat(exitCode, equalTo(0)); ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect: " + containerInspectResponse.toString()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); assertThat(containerInspectResponse.getState().running, is(equalTo(false))); assertThat(containerInspectResponse.getState().exitCode, is(equalTo(exitCode))); @@ -278,7 +297,7 @@ public void testLogs() throws DockerException, IOException { containerConfig.setCmd(new String[] {"/bin/echo", snippet}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); @@ -305,8 +324,8 @@ public void testLogs() throws DockerException, IOException { String fullLog = logwriter.toString(); - LOG.info("Container log: " + fullLog); - assertThat(fullLog, equalTo(snippet)); + LOG.info("Container log: {}", fullLog); + assertThat(fullLog, endsWith(snippet)); } @Test @@ -316,7 +335,7 @@ public void testDiff() throws DockerException { containerConfig.setCmd(new String[] {"touch", "/test"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); boolean add = tmpContainers.add(container.getId()); @@ -324,9 +343,9 @@ public void testDiff() throws DockerException { assertThat(exitCode, equalTo(0)); List filesystemDiff = dockerClient.containterDiff(container.getId()); - LOG.info("Container DIFF: " + filesystemDiff.toString()); + LOG.info("Container DIFF: {}", filesystemDiff.toString()); - assertThat(filesystemDiff.size(), equalTo(4)); + assertThat(filesystemDiff.size(), equalTo(3)); ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); assertThat(testChangeLog, hasField("path", equalTo("/test"))); @@ -341,16 +360,16 @@ public void testStopContainer() throws DockerException { containerConfig.setCmd(new String[] {"sleep", "9999"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); tmpContainers.add(container.getId()); - LOG.info("Stopping container " + container.getId()); + LOG.info("Stopping container: {}", container.getId()); dockerClient.stopContainer(container.getId(), 2); ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); assertThat(containerInspectResponse.getState().running, is(equalTo(false))); assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); @@ -364,16 +383,16 @@ public void testKillContainer() throws DockerException { containerConfig.setCmd(new String[] {"sleep", "9999"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); tmpContainers.add(container.getId()); - LOG.info("Killing container " + container.getId()); + LOG.info("Killing container: {}", container.getId()); dockerClient.kill(container.getId()); ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); assertThat(containerInspectResponse.getState().running, is(equalTo(false))); assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0))); @@ -388,20 +407,20 @@ public void restartContainer() throws DockerException { containerConfig.setCmd(new String[] {"sleep", "9999"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); tmpContainers.add(container.getId()); ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect:" + containerInspectResponse.toString()); + LOG.info("Container Inspect: {}", containerInspectResponse.toString()); String startTime = containerInspectResponse.getState().startedAt; dockerClient.restart(container.getId(), 2); ContainerInspectResponse containerInspectResponse2 = dockerClient.inspectContainer(container.getId()); - LOG.info("Container Inspect After Restart:" + containerInspectResponse2.toString()); + LOG.info("Container Inspect After Restart: {}", containerInspectResponse2.toString()); String startTime2 = containerInspectResponse2.getState().startedAt; @@ -425,7 +444,7 @@ public void removeContainer() throws DockerException { dockerClient.waitContainer(container.getId()); tmpContainers.add(container.getId()); - LOG.info("Removing container " + container.getId()); + LOG.info("Removing container: {}", container.getId()); dockerClient.removeContainer(container.getId()); List containers2 = dockerClient.listContainers(true); @@ -443,17 +462,17 @@ public void removeContainer() throws DockerException { @Test public void testPullImage() throws DockerException, IOException { - String testImage = "joffrey/test001"; + String testImage = "kpelykh/vimbase"; - LOG.info("Removing image " + testImage); + LOG.info("Removing image: {}", testImage); dockerClient.removeImage(testImage); Info info = dockerClient.info(); - LOG.info("Client info " + info.toString()); + LOG.info("Client info: {}", info.toString()); int imgCount= info.getImages(); - LOG.info("Pulling image " + testImage); + LOG.info("Pulling image: {}", testImage); ClientResponse response = dockerClient.pull(testImage); @@ -471,17 +490,17 @@ public void testPullImage() throws DockerException, IOException { } String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Pulling repository joffrey/test001")); + assertThat(fullLog, containsString("Pulling repository kpelykh/vimbase")); tmpImgs.add(testImage); info = dockerClient.info(); - LOG.info("Client info after pull " + info.toString()); + LOG.info("Client info after pull, {}", info.toString()); - assertThat(imgCount + 2, equalTo(info.getImages())); + assertThat(imgCount + 1, equalTo(info.getImages())); ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(testImage); - LOG.info("Image Inspect: " + imageInspectResponse.toString()); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); assertThat(imageInspectResponse, notNullValue()); } @@ -494,17 +513,17 @@ public void commitImage() throws DockerException { containerConfig.setCmd(new String[] {"touch", "/test"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + 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.Builder(container.getId()).build()); + 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()); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); assertThat(imageInspectResponse, hasField("container", startsWith(container.getId()))); assertThat(imageInspectResponse.getContainerConfig().getImage(), equalTo("busybox")); @@ -515,7 +534,7 @@ public void commitImage() throws DockerException { } @Test - public void testRemoveImage() throws DockerException { + public void testRemoveImage() throws DockerException, InterruptedException { ContainerConfig containerConfig = new ContainerConfig(); @@ -523,17 +542,21 @@ public void testRemoveImage() throws DockerException { containerConfig.setCmd(new String[] {"touch", "/test"}); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + 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.Builder(container.getId()).build()); + LOG.info("Commiting container {}", container.toString()); + String imageId = dockerClient.commit(new CommitConfig(container.getId())); tmpImgs.add(imageId); - LOG.info("Removing image" + 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); @@ -563,7 +586,7 @@ public void testRunShlex() throws DockerException { }; for (String command : commands) { - LOG.info("Running command [" + command + "]"); + LOG.info("Running command: [{}]", command); ContainerConfig containerConfig = new ContainerConfig(); containerConfig.setImage("busybox"); @@ -578,7 +601,7 @@ public void testRunShlex() throws DockerException { } - @Test + @Test(enabled = false) public void testNginxDockerfileBuilder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); @@ -604,25 +627,25 @@ public void testNginxDockerfileBuilder() throws DockerException, IOException { ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect:" + imageInspectResponse.toString()); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); tmpImgs.add(imageInspectResponse.getId()); assertThat(imageInspectResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); } - @Test + @Test(enabled = false) public void testDockerBuilderAddFile() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile()); dockerfileBuild(baseDir, "Successfully executed testrun.sh"); } - @Test + @Test(enabled = false) public void testDockerBuilderAddFolder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile()); dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh"); } - @Test + @Test(enabled = false) public void testNetCatDockerfileBuilder() throws DockerException, IOException, InterruptedException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); @@ -648,7 +671,7 @@ public void testNetCatDockerfileBuilder() throws DockerException, IOException, I ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); assertThat(imageInspectResponse, not(nullValue())); - LOG.info("Image Inspect:" + imageInspectResponse.toString()); + LOG.info("Image Inspect: {}", imageInspectResponse.toString()); tmpImgs.add(imageInspectResponse.getId()); ContainerConfig containerConfig = new ContainerConfig(); @@ -661,18 +684,18 @@ public void testNetCatDockerfileBuilder() throws DockerException, IOException, I ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId()); assertThat(containerInspectResponse.getId(), notNullValue()); - assertThat(containerInspectResponse.getNetworkSettings().portMapping, notNullValue()); - int port = Integer.valueOf(containerInspectResponse.getNetworkSettings().portMapping.get("Tcp").get("6900")); - + assertThat(containerInspectResponse.getNetworkSettings().ports, notNullValue()); - LOG.info("Checking port {} is open", port); - assertThat(available(port), is(false)); + //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); - LOG.info("Checking port {} is closed", port); - assertThat(available(port), is(true)); - } @@ -741,7 +764,7 @@ private void dockerfileBuild(File baseDir, String expectedText) throws DockerExc ContainerConfig containerConfig = new ContainerConfig(); containerConfig.setImage(imageId); ContainerCreateResponse container = dockerClient.createContainer(containerConfig); - LOG.info("Created container " + container.toString()); + LOG.info("Created container: {}", container.toString()); assertThat(container.getId(), not(isEmptyString())); dockerClient.startContainer(container.getId()); From 3761f1aea696c5f5645577319ca2318b69bb7119 Mon Sep 17 00:00:00 2001 From: kpelykh Date: Tue, 4 Feb 2014 22:01:02 -0800 Subject: [PATCH 14/72] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2219c66a..406f3ca1 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,12 @@ Run build with tests: $ mvn clean install -## Docker Java Client usage: - -docker-java is vailable though Maven Central, so you can include the following dependency into your pom.xml: +## Docker-Java maven dependency: com.kpelykh docker-java - 0.7.6 + 0.7.6-SNAPSHOT From 7b3763fc515783ee3f01568c2ad7d75389856bc0 Mon Sep 17 00:00:00 2001 From: kpelykh Date: Wed, 5 Feb 2014 14:14:30 -0800 Subject: [PATCH 15/72] fixed all the tests --- .../kpelykh/docker/client/DockerClient.java | 10 +++--- .../kpelykh/docker/client/model/Ports.java | 10 +++--- .../docker/client/test/DockerClientTest.java | 32 +++++-------------- 3 files changed, 19 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 103713d6..7312d5fa 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -643,20 +643,20 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder); for (String cmd : dockerFileContent) { - if (StringUtils.startsWith(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)); } File src = new File(addArgs[1]); - /* if (!src.isAbsolute()) { - src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); + if (!src.isAbsolute()) { + src = new File(dockerFolder, addArgs[1]).getCanonicalFile(); } if (!src.exists()) { - throw new DockerException(String.format("Sorce file %s doesnt' exist", src)); - }*/ + throw new DockerException(String.format("Source file %s doesnt' exist", src)); + } if (src.isDirectory()) { FileUtils.copyDirectory(src, tmpDockerContextFolder); } else { 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 17f57b6e..d9fdab60 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Ports.java +++ b/src/main/java/com/kpelykh/docker/client/model/Ports.java @@ -7,6 +7,7 @@ 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 java.io.IOException; import java.util.HashMap; @@ -95,10 +96,11 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali for (Iterator> it = node.getFields(); it.hasNext();) { Map.Entry field = it.next(); - String hostIp = field.getValue().get(0).get("HostIp").getTextValue(); - String hostPort = field.getValue().get(0).get("HostPort").getTextValue(); - out.addPort(Port.makePort(field.getKey(), hostIp, hostPort)); - + if (!field.getValue().equals(NullNode.getInstance())) { + String hostIp = field.getValue().get(0).get("HostIp").getTextValue(); + String hostPort = field.getValue().get(0).get("HostPort").getTextValue(); + out.addPort(Port.makePort(field.getKey(), hostIp, hostPort)); + } } return out; } 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 73cbb8bf..06656efa 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -244,22 +244,6 @@ public void testStartContainer() throws DockerException { } - /* @Test - public void testStartContainer2() throws DockerException {ContainerConfig appContainerConfig = new ContainerConfig(); - appContainerConfig.setImage("4096e911ada1"); - ContainerCreateResponse appContResponse = dockerClient.createContainer(appContainerConfig, "AppContainer"); - System.out.println("Created an App container successfully: " + appContResponse.getId()); - String appContId = appContResponse.getId(); - HostConfig appHostConfig = new HostConfig(null); - Port p = new Port("tcp","8080","0.0.0.0","8082"); - Ports ports = new Ports(); - ports.addPort(p); - appHostConfig.setPortBindings(ports); - String[] links = {"mariaDB3:db"}; - appHostConfig.setLinks(links); - dockerClient.startContainer(appContId, appHostConfig); - } -*/ @Test public void testWaitContainer() throws DockerException { @@ -601,7 +585,7 @@ public void testRunShlex() throws DockerException { } - @Test(enabled = false) + @Test public void testNginxDockerfileBuilder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile()); @@ -623,7 +607,7 @@ public void testNginxDockerfileBuilder() throws DockerException, IOException { String fullLog = logwriter.toString(); assertThat(fullLog, containsString("Successfully built")); - String imageId = StringUtils.substringAfterLast(fullLog, "Successfully built ").trim(); + String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); assertThat(imageInspectResponse, not(nullValue())); @@ -633,19 +617,19 @@ public void testNginxDockerfileBuilder() throws DockerException, IOException { assertThat(imageInspectResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\"")); } - @Test(enabled = false) + @Test public void testDockerBuilderAddFile() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile()); dockerfileBuild(baseDir, "Successfully executed testrun.sh"); } - @Test(enabled = false) + @Test public void testDockerBuilderAddFolder() throws DockerException, IOException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile()); dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh"); } - @Test(enabled = false) + @Test public void testNetCatDockerfileBuilder() throws DockerException, IOException, InterruptedException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); @@ -667,7 +651,7 @@ public void testNetCatDockerfileBuilder() throws DockerException, IOException, I String fullLog = logwriter.toString(); assertThat(fullLog, containsString("Successfully built")); - String imageId = StringUtils.substringAfterLast(fullLog, "Successfully built ").trim(); + String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId); assertThat(imageInspectResponse, not(nullValue())); @@ -758,7 +742,7 @@ private void dockerfileBuild(File baseDir, String expectedText) throws DockerExc String fullLog = logwriter.toString(); assertThat(fullLog, containsString("Successfully built")); - String imageId = StringUtils.substringAfterLast(fullLog, "Successfully built ").trim(); + String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim(); //Create container based on image ContainerConfig containerConfig = new ContainerConfig(); @@ -788,6 +772,6 @@ private void dockerfileBuild(File baseDir, String expectedText) throws DockerExc IOUtils.closeQuietly(logResponse.getEntityInputStream()); } - assertThat(logwriter2.toString(), equalTo(expectedText)); + assertThat(logwriter2.toString(), endsWith(expectedText)); } } \ No newline at end of file From 29379a9c00e5367711d1a54c845bfa3840ef6e8e Mon Sep 17 00:00:00 2001 From: abhijeet-devops Date: Thu, 6 Feb 2014 21:20:35 -0800 Subject: [PATCH 16/72] Adding after ADD command to not to confuse with other non-dockerfile commands like add-apt-repository etc. --- 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 7312d5fa..4981893f 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 41e9079bf388914a87a5ee8ad9fcd791beb0c55d Mon Sep 17 00:00:00 2001 From: "Kevin A. Archie" Date: Mon, 10 Feb 2014 12:03:05 -0600 Subject: [PATCH 17/72] let m2eclipse generate .classpath; m2eclipse needs pluginManagement in POM --- .gitignore | 1 + pom.xml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2fc61df1..86139491 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.swp .project .settings +.classpath # Ignore all build/dist directories target diff --git a/pom.xml b/pom.xml index 7e24e77e..be72410e 100644 --- a/pom.xml +++ b/pom.xml @@ -188,7 +188,7 @@ - + @@ -271,6 +271,7 @@ + From 4a48d0e1a89dcceddcc6beec25955cd98f912e2e Mon Sep 17 00:00:00 2001 From: "Joel L. Tucci" Date: Wed, 26 Feb 2014 16:57:50 +0900 Subject: [PATCH 18/72] Added new fields to comply with Docker 0.8.1 API changes --- .../kpelykh/docker/client/model/ContainerConfig.java | 9 +++++++++ .../java/com/kpelykh/docker/client/model/Info.java | 10 ++++++++++ 2 files changed, 19 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..52bf2da5 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,7 @@ public class ContainerConfig { @JsonProperty("Domainname") private String domainName = ""; // FIXME Is this the right type? -BJE @JsonProperty("ExposedPorts") private Map exposedPorts; + @JsonProperty("OnBuild") private String[] onBuild; public Map getExposedPorts() { return exposedPorts; @@ -242,6 +243,14 @@ public ContainerConfig setEntrypoint(String[] entrypoint) { return this; } + public String[] getOnBuild() { + return onBuild; + } + + public void setOnBuild(String[] onBuild) { + this.onBuild=onBuild; + } + @Override public String toString() { return "ContainerConfig{" + 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..f340dc81 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Info.java +++ b/src/main/java/com/kpelykh/docker/client/model/Info.java @@ -63,6 +63,9 @@ public class Info { @JsonProperty("SwapLimit") private int swapLimit; + @JsonProperty("ExecutionDriver") + private String executionDriver; + public boolean isDebug() { return debug; } @@ -190,6 +193,13 @@ public int getSwapLimit() { 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() { From 7d5110d850936cce5d0263aefc21a4a2a594631e Mon Sep 17 00:00:00 2001 From: kpelykh Date: Wed, 26 Feb 2014 00:09:41 -0800 Subject: [PATCH 19/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 406f3ca1..f80d707a 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.8, Docker Server version 0.7.6+ and 0.8.1 ## Build with Maven From f19fd197500d5827763782069e8e54b01bacd7ab Mon Sep 17 00:00:00 2001 From: Ryan Campbell Date: Wed, 26 Feb 2014 12:08:05 -0800 Subject: [PATCH 20/72] Throw a NotFoundException when 404's are received so that these can be handled more easily. This change is backwards compatible. Looking for things that aren't there is a common use-case, so it should be easy to do. --- .../kpelykh/docker/client/DockerClient.java | 37 ++++++++++--------- .../docker/client/NotFoundException.java | 20 ++++++++++ 2 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/NotFoundException.java diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 4981893f..7c2ca280 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -254,7 +254,7 @@ public List getImages(String name, boolean allImages) throws DockerExcept } - public ImageInspectResponse inspectImage(String imageId) throws DockerException { + public ImageInspectResponse inspectImage(String imageId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId)); @@ -263,7 +263,7 @@ public ImageInspectResponse inspectImage(String imageId) throws DockerException return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such image %s", imageId)); + throw new NotFoundException(String.format("No such image %s", imageId)); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -318,7 +318,7 @@ public ContainerCreateResponse createContainer(ContainerConfig config) throws Do return createContainer(config, null); } - public ContainerCreateResponse createContainer(ContainerConfig config,String name) throws DockerException { + public ContainerCreateResponse createContainer(ContainerConfig config,String name) throws DockerException, NotFoundException { MultivaluedMap params = new MultivaluedMapImpl(); if(name != null){ @@ -333,7 +333,7 @@ public ContainerCreateResponse createContainer(ContainerConfig config,String nam .post(ContainerCreateResponse.class, config); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage())); + 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) { @@ -349,7 +349,7 @@ public void startContainer(String containerId) throws DockerException { this.startContainer(containerId, null); } - public void startContainer(String containerId, HostConfig hostConfig) throws DockerException { + public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId)); @@ -363,7 +363,7 @@ public void startContainer(String containerId, HostConfig hostConfig) throws Doc } } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 204) { //no error LOGGER.trace("Successfully started container {}", containerId); @@ -375,7 +375,7 @@ public void startContainer(String containerId, HostConfig hostConfig) throws Doc } } - public ContainerInspectResponse inspectContainer(String containerId) throws DockerException { + public ContainerInspectResponse inspectContainer(String containerId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId)); @@ -384,7 +384,7 @@ public ContainerInspectResponse inspectContainer(String containerId) throws Dock return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -414,6 +414,7 @@ public void removeContainer(String containerId, boolean removeVolumes) throws Do } 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); @@ -432,7 +433,7 @@ public void removeContainers(List containers, boolean removeVolumes) thr } } - public int waitContainer(String containerId) throws DockerException { + public int waitContainer(String containerId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId)); try { @@ -441,7 +442,7 @@ public int waitContainer(String containerId) throws DockerException { return jsonObject.getInt("StatusCode"); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -461,7 +462,7 @@ public ClientResponse logContainerStream(String containerId) throws DockerExcept return logContainer(containerId, true); } - private ClientResponse logContainer(String containerId, boolean stream) throws DockerException { + private ClientResponse logContainer(String containerId, boolean stream) throws DockerException, NotFoundException { MultivaluedMap params = new MultivaluedMapImpl(); params.add("logs", "1"); params.add("stdout", "1"); @@ -480,7 +481,7 @@ private ClientResponse logContainer(String containerId, boolean stream) throws D 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)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -489,7 +490,7 @@ private ClientResponse logContainer(String containerId, boolean stream) throws D } } - public List containterDiff(String containerId) throws DockerException { + public List containterDiff(String containerId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); @@ -498,7 +499,7 @@ public List containterDiff(String containerId) throws DockerException return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType>() {}); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { @@ -557,7 +558,7 @@ public void kill(String containerId) throws DockerException { } } - public void restart(String containerId, int timeout) throws DockerException { + public void restart(String containerId, int timeout) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId)); try { @@ -565,7 +566,7 @@ public void restart(String containerId, int timeout) throws DockerException { webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", containerId)); + throw new NotFoundException(String.format("No such container %s", containerId)); } else if (exception.getResponse().getStatus() == 204) { //no error LOGGER.trace("Successfully restarted container {}", containerId); @@ -577,7 +578,7 @@ public void restart(String containerId, int timeout) throws DockerException { } } - public String commit(CommitConfig commitConfig) throws DockerException { + public String commit(CommitConfig commitConfig) throws DockerException, NotFoundException { Preconditions.checkNotNull(commitConfig.getContainer(), "Container ID was not specified"); MultivaluedMap params = new MultivaluedMapImpl(); @@ -596,7 +597,7 @@ public String commit(CommitConfig commitConfig) throws DockerException { return jsonObject.getString("Id"); } catch (UniformInterfaceException exception) { if (exception.getResponse().getStatus() == 404) { - throw new DockerException(String.format("No such container %s", commitConfig.getContainer())); + throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer())); } else if (exception.getResponse().getStatus() == 500) { throw new DockerException("Server error", exception); } else { diff --git a/src/main/java/com/kpelykh/docker/client/NotFoundException.java b/src/main/java/com/kpelykh/docker/client/NotFoundException.java new file mode 100644 index 00000000..f6c8fe54 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/NotFoundException.java @@ -0,0 +1,20 @@ +package com.kpelykh.docker.client; + +/** + * Indicates that the given entity does not exist. + * + * @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); + } +} From 9be43bcf903ce3250e6845b96d15e50171774e4a Mon Sep 17 00:00:00 2001 From: Ryan Campbell Date: Thu, 27 Feb 2014 10:22:56 -0800 Subject: [PATCH 21/72] Added importImage to support creating images from tar files --- .../kpelykh/docker/client/DockerClient.java | 34 ++++++++++++++++++ .../client/model/ImageCreateResponse.java | 30 ++++++++++++++++ .../docker/client/test/DockerClientTest.java | 7 ++++ .../testImportImageFromTar/empty.tar | Bin 0 -> 10240 bytes 4 files changed, 71 insertions(+) create mode 100644 src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java create mode 100644 src/test/resources/testImportImageFromTar/empty.tar diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index 7c2ca280..be896a91 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -30,6 +30,7 @@ import javax.ws.rs.core.MultivaluedMap; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.UUID; @@ -150,6 +151,39 @@ public ClientResponse pull(String repository, String tag, String registry) throw } } + /** + * 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 { diff --git a/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java new file mode 100644 index 00000000..4be68072 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java @@ -0,0 +1,30 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Arrays; + +/** + * Parse reponses from /images/create + * + * @author Ryan Campbell (ryan.campbell@gmail.com) + * + */ +public class ImageCreateResponse { + + @JsonProperty("status") + private String id; + + + public String getId() { + return id; + } + + + @Override + public String toString() { + return "ContainerCreateResponse{" + + "id='" + id + '\'' + + '}'; + } +} 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..a035f146 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -629,6 +629,13 @@ public void testDockerBuilderAddFolder() throws DockerException, IOException { dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh"); } + @Test + public void testImportImageFromTar() throws DockerException, IOException { + InputStream tar = Thread.currentThread().getContextClassLoader().getResourceAsStream("testImportImageFromTar/empty.tar"); + String imageId = dockerClient.importImage("empty", null, tar).getId(); + assert imageId.contains(dockerClient.inspectImage("empty").getId()); + } + @Test public void testNetCatDockerfileBuilder() throws DockerException, IOException, InterruptedException { File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile()); diff --git a/src/test/resources/testImportImageFromTar/empty.tar b/src/test/resources/testImportImageFromTar/empty.tar new file mode 100644 index 0000000000000000000000000000000000000000..b055b9c22243fba41c55c21de8a99d7455894d56 GIT binary patch literal 10240 zcmeIuF%rTc5Cu?9Tc0=x6Bw|m=8;n1X>T1t4; zp6~iT8^)aSRL?c{dqb+@6k<7atIy}_qg|F5!!plpZ{Dx|-djBa1PBlyK!5-N0t5&U jAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly@MnQ1TDcM< literal 0 HcmV?d00001 From d88faa9e5054ac5213aef02e4060eb8755fe8746 Mon Sep 17 00:00:00 2001 From: Dusan Katona Date: Mon, 3 Mar 2014 19:06:29 +0100 Subject: [PATCH 22/72] Allow to get names from container --- .../java/com/kpelykh/docker/client/model/Container.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 c9de7434..8a87ebc0 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Container.java +++ b/src/main/java/com/kpelykh/docker/client/model/Container.java @@ -48,6 +48,9 @@ public class Container { @JsonProperty("SizeRootFs") private int sizeRootFs; + @JsonProperty("Names") + private String[] names; + public String getId() { return id; } @@ -84,6 +87,10 @@ public int getSizeRootFs() { return sizeRootFs; } + public String[] getNames() { + return names; + } + @Override public String toString() { return "Container{" + @@ -95,6 +102,7 @@ public String toString() { ", ports=" + ports + ", size=" + size + ", sizeRootFs=" + sizeRootFs + + ", names=" + Arrays.toString(names) + '}'; } } From dddfb1c32f9dd67a45e43d2e0d7b0562b419625a Mon Sep 17 00:00:00 2001 From: Dusan Katona Date: Mon, 3 Mar 2014 19:08:01 +0100 Subject: [PATCH 23/72] Add setters to Container and to ContainerCreateResponse This allows using these objects in tests. --- .../docker/client/model/Container.java | 32 +++++++++++++++++++ .../client/model/ContainerCreateResponse.java | 8 +++++ 2 files changed, 40 insertions(+) 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 8a87ebc0..14970c3c 100644 --- a/src/main/java/com/kpelykh/docker/client/model/Container.java +++ b/src/main/java/com/kpelykh/docker/client/model/Container.java @@ -91,6 +91,38 @@ public String[] getNames() { return names; } + public void setId(String id) { + this.id = id; + } + + public void setCommand(String command) { + this.command = command; + } + + public void setImage(String image) { + this.image = image; + } + + public void setCreated(long created) { + this.created = created; + } + + public void setStatus(String status) { + this.status = status; + } + + public void setSize(int size) { + this.size = size; + } + + public void setSizeRootFs(int sizeRootFs) { + this.sizeRootFs = sizeRootFs; + } + + public void setNames(String[] names) { + this.names = names; + } + @Override public String toString() { return "Container{" + 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 c0ef5bdc..d56d6773 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java @@ -25,6 +25,14 @@ public String[] getWarnings() { return warnings; } + public void setId(String id) { + this.id = id; + } + + public void setWarnings(String[] warnings) { + this.warnings = warnings; + } + @Override public String toString() { return "ContainerCreateResponse{" + From e3237b436f9245d7c60fe379562e18c979116050 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Mon, 3 Mar 2014 11:24:48 -0800 Subject: [PATCH 24/72] replaced kpelykh/vimbase image with ubuntu --- README.md | 12 ++++++------ pom.xml | 2 +- .../kpelykh/docker/client/test/DockerClientTest.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f80d707a..5a49f8ad 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+ and 0.8.1 +Supports a subset of the Docker Client API v1.8, Docker Server version 0.8.1 ## Build with Maven @@ -32,13 +32,13 @@ Now make sure that docker is up: $ docker -H tcp://127.0.0.1:4243 version - Client version: 0.7.6 + Client version: 0.8.1 Go version (client): go1.2 - Git commit (client): bc3b2ec - Server version: 0.7.6 - Git commit (server): bc3b2ec + Git commit (client): a1598d1 + Server version: 0.8.1 + Git commit (server): a1598d1 Go version (server): go1.2 - Last stable version: 0.7.6 + Last stable version: 0.8.1 Run build with tests: diff --git a/pom.xml b/pom.xml index be72410e..bbd94de4 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.kpelykh docker-java jar - 0.7.6-SNAPSHOT + 0.8.1-SNAPSHOT docker-java https://github.com/kpelykh/docker-java 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..8125ff58 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -446,7 +446,7 @@ public void removeContainer() throws DockerException { @Test public void testPullImage() throws DockerException, IOException { - String testImage = "kpelykh/vimbase"; + String testImage = "ubuntu"; LOG.info("Removing image: {}", testImage); dockerClient.removeImage(testImage); @@ -474,7 +474,7 @@ public void testPullImage() throws DockerException, IOException { } String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Pulling repository kpelykh/vimbase")); + assertThat(fullLog, containsString("Pulling repository ubuntu")); tmpImgs.add(testImage); From 135f71c73a344a9bf2ea6c892a8dbb65725e32a9 Mon Sep 17 00:00:00 2001 From: kpelykh Date: Mon, 3 Mar 2014 11:30:43 -0800 Subject: [PATCH 25/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a49f8ad..594b0574 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Run build with tests: com.kpelykh docker-java - 0.7.6-SNAPSHOT + 0.8.1-SNAPSHOT From 2a6d92da74343d7906ebfb0678eb7d3b1b8f5735 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 11:33:42 -0800 Subject: [PATCH 26/72] fixed tests --- README.md | 2 +- .../docker/client/test/DockerClientTest.java | 15 +++++++++++---- src/test/resources/testAddFile/Dockerfile | 2 +- src/test/resources/testAddFolder/Dockerfile | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 594b0574..2dd43ecf 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Run build with tests: com.kpelykh docker-java - 0.8.1-SNAPSHOT + 0.8.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 8305eb00..3268ed56 100644 --- a/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java +++ b/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java @@ -312,6 +312,10 @@ public void testLogs() throws DockerException, IOException { assertThat(fullLog, endsWith(snippet)); } + //This test doesn't work in Ubuntu 12.04 due to + //Error mounting '/dev/mapper/docker-8:5-... + //ref: https://github.com/dotcloud/docker/issues/4036 + @Test public void testDiff() throws DockerException { ContainerConfig containerConfig = new ContainerConfig(); @@ -329,7 +333,7 @@ public void testDiff() throws DockerException { List filesystemDiff = dockerClient.containterDiff(container.getId()); LOG.info("Container DIFF: {}", filesystemDiff.toString()); - assertThat(filesystemDiff.size(), equalTo(3)); + assertThat(filesystemDiff.size(), equalTo(1)); ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test"))); assertThat(testChangeLog, hasField("path", equalTo("/test"))); @@ -446,7 +450,7 @@ public void removeContainer() throws DockerException { @Test public void testPullImage() throws DockerException, IOException { - String testImage = "ubuntu"; + String testImage = "centos"; LOG.info("Removing image: {}", testImage); dockerClient.removeImage(testImage); @@ -474,20 +478,23 @@ public void testPullImage() throws DockerException, IOException { } String fullLog = logwriter.toString(); - assertThat(fullLog, containsString("Pulling repository ubuntu")); + assertThat(fullLog, containsString("Download complete")); tmpImgs.add(testImage); 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); LOG.info("Image Inspect: {}", imageInspectResponse.toString()); assertThat(imageInspectResponse, notNullValue()); } + //This test doesn't work in Ubuntu 12.04 due to + //Error mounting '/dev/mapper/docker-8:5-... + //ref: https://github.com/dotcloud/docker/issues/4036 @Test public void commitImage() throws DockerException { diff --git a/src/test/resources/testAddFile/Dockerfile b/src/test/resources/testAddFile/Dockerfile index 6efbf091..38afcdd4 100644 --- a/src/test/resources/testAddFile/Dockerfile +++ b/src/test/resources/testAddFile/Dockerfile @@ -2,7 +2,7 @@ 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 diff --git a/src/test/resources/testAddFolder/Dockerfile b/src/test/resources/testAddFolder/Dockerfile index 73173ad4..b2a8e2a1 100644 --- a/src/test/resources/testAddFolder/Dockerfile +++ b/src/test/resources/testAddFolder/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu # Copy testrun.sh files into the container -add . /src/ +ADD . /src/ run ls -la /src From 2cf6c69330082c0cd09eb6f6762bc8127ae7613c Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 11:48:01 -0800 Subject: [PATCH 27/72] fixed scm url --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bbd94de4..bf43ae4d 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ scm:git:git@github.com:kpelykh/docker-java.git - 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 From 6a32587f239949bddc58c8f4f9a62cacf90a6576 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:18:50 -0800 Subject: [PATCH 28/72] [maven-release-plugin] prepare release docker-java-0.8.1 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index bf43ae4d..0dc9c21e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ - + 4.0.0 @@ -11,7 +10,7 @@ com.kpelykh docker-java jar - 0.8.1-SNAPSHOT + 0.8.1 docker-java https://github.com/kpelykh/docker-java @@ -29,7 +28,8 @@ 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 - + docker-java-0.8.1 + From 32cc7946001a32d8fa36efba331ab3c4c3aa6e12 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:18:54 -0800 Subject: [PATCH 29/72] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0dc9c21e..2369e4c2 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.kpelykh docker-java jar - 0.8.1 + 0.8.2-SNAPSHOT docker-java https://github.com/kpelykh/docker-java @@ -28,7 +28,7 @@ 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 - docker-java-0.8.1 + HEAD From ee70971f1180d35c3cb7c195d0497546684ea6ec Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:30:21 -0800 Subject: [PATCH 30/72] disabled tests by default can be enabled during build with mvn install -DskipTests=false --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 2369e4c2..de68e55f 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,8 @@ + true + UTF-8 true false @@ -227,6 +229,9 @@ org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} + + ${skipTests} + From 825937354453e6aaefa5b85455375b563806c9dd Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:31:07 -0800 Subject: [PATCH 31/72] reverting back to 0.8.1-SNAPSHOT --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index de68e55f..629a5916 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.kpelykh docker-java jar - 0.8.2-SNAPSHOT + 0.8.1-SNAPSHOT docker-java https://github.com/kpelykh/docker-java @@ -28,7 +28,6 @@ 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 - HEAD From 8beb3e185d1b321e651752c3a69bf933949bef07 Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:32:20 -0800 Subject: [PATCH 32/72] [maven-release-plugin] prepare release docker-java-0.8.1 --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 629a5916..e0ee6720 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.kpelykh docker-java jar - 0.8.1-SNAPSHOT + 0.8.1 docker-java https://github.com/kpelykh/docker-java @@ -28,6 +28,7 @@ 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 + docker-java-0.8.1 From 77c984804762fdf56c01e046304cd54aeb20d0bf Mon Sep 17 00:00:00 2001 From: Konstantin Pelykh Date: Wed, 5 Mar 2014 12:32:25 -0800 Subject: [PATCH 33/72] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e0ee6720..7929bcb3 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.kpelykh docker-java jar - 0.8.1 + 0.8.2-SNAPSHOT docker-java https://github.com/kpelykh/docker-java @@ -28,7 +28,7 @@ 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 - docker-java-0.8.1 + HEAD From 6168a2172ecfc128d37497646084a7e964b7cc0d Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 7 Mar 2014 11:58:00 +0100 Subject: [PATCH 34/72] https://github.com/kpelykh/docker-java/issues/31 --- .../java/com/kpelykh/docker/client/DockerClient.java | 9 ++++++++- 1 file changed, 8 insertions(+), 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 be896a91..e673c9c5 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -646,8 +646,12 @@ public String commit(CommitConfig commitConfig) throws DockerException, NotFound 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, null, 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); @@ -657,6 +661,9 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio MultivaluedMap params = new MultivaluedMapImpl(); params.add("t", tag); + if(noCache) { + params.add("nocache", ""); + } // ARCHIVE TAR String archiveNameWithOutExtension = UUID.randomUUID().toString(); From a09af1be3339249168b155c651a3ae25105a3b57 Mon Sep 17 00:00:00 2001 From: Marcus Linke Date: Fri, 7 Mar 2014 11:58:00 +0100 Subject: [PATCH 35/72] https://github.com/kpelykh/docker-java/issues/31 --- .../java/com/kpelykh/docker/client/DockerClient.java | 9 ++++++++- 1 file changed, 8 insertions(+), 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 be896a91..b214efb5 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -646,8 +646,12 @@ public String commit(CommitConfig commitConfig) throws DockerException, NotFound 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, null, 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); @@ -657,6 +661,9 @@ public ClientResponse build(File dockerFolder, String tag) throws DockerExceptio MultivaluedMap params = new MultivaluedMapImpl(); params.add("t", tag); + if(noCache) { + params.add("nocache", "true"); + } // ARCHIVE TAR String archiveNameWithOutExtension = UUID.randomUUID().toString(); From ec08b6b149a4940236cac2ab32019691549e4a40 Mon Sep 17 00:00:00 2001 From: "Kevin A. Archie" Date: Wed, 12 Mar 2014 13:32:23 -0500 Subject: [PATCH 36/72] added BoundHostVolumes for host directories bound as in-container volumes --- .../docker/client/model/BoundHostVolumes.java | 93 +++++++++++++++++++ .../docker/client/model/ContainerConfig.java | 6 +- .../docker/client/model/HostConfig.java | 4 + 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java diff --git a/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java b/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java new file mode 100644 index 00000000..c5c30de4 --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java @@ -0,0 +1,93 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.kpelykh.docker.client.model; + +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 + * + */ +@JsonSerialize(using=BoundHostVolumes.Serializer.class) +public class BoundHostVolumes { + private static final String[] STRING_ARRAY = new String[0]; + private final String[] dests, binds; + + /** + * + * @param specs Iterable of String binding specs, each of form "{host-path}:{container-patch}:[rw|ro]" + * @throws MalformedVolumeSpecException if any specs are null or empty + */ + public BoundHostVolumes(final Iterable specs) { + final List dests = new ArrayList(), binds = new ArrayList(); + for (final String spec : specs) { + if (null == spec || "".equals(spec)) { + // skip empty spec lines + } else { + final String[] sspec = spec.split(":"); + dests.add(sspec.length > 1 ? sspec[1] : sspec[0]); + binds.add(spec); + } + } + this.dests = dests.toArray(STRING_ARRAY); + this.binds = binds.toArray(STRING_ARRAY); + } + + public String[] asBinds() { + return binds; + } + + private BoundHostVolumes writeVolumes(final JsonGenerator jg) throws IOException { + jg.writeStartObject(); + for (final String dest : dests) { + jg.writeObjectFieldStart(dest); + jg.writeEndObject(); + } + jg.writeEndObject(); + return this; + } + + /** + * This is an ugly hack. We assume that the serializer only gets called when + * a containing ContainerConfig gets serialized, when POSTing to + * /containers/create . In that context, we pass only the container-path + * part (the key in the volumes map). + * + * @author Kevin A. Archie + * + */ + public static class Serializer extends JsonSerializer { + /* (non-Javadoc) + * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider) + */ + @Override + public void serialize(final BoundHostVolumes volumes, final JsonGenerator jg, final SerializerProvider sp) + throws IOException { + volumes.writeVolumes(jg); + } + } +} 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 52bf2da5..a756a4e5 100644 --- a/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java @@ -28,7 +28,7 @@ public class ContainerConfig { @JsonProperty("Cmd") private String[] cmd; @JsonProperty("Dns") private String[] dns; @JsonProperty("Image") private String image; - @JsonProperty("Volumes") private Object volumes; + @JsonProperty("Volumes") private BoundHostVolumes volumes; @JsonProperty("VolumesFrom") private String volumesFrom = ""; @JsonProperty("Entrypoint") private String[] entrypoint = new String[]{}; @JsonProperty("NetworkDisabled") private boolean networkDisabled = false; @@ -216,11 +216,11 @@ public ContainerConfig setImage(String image) { return this; } - public Object getVolumes() { + public BoundHostVolumes getVolumes() { return volumes; } - public ContainerConfig setVolumes(Object volumes) { + public ContainerConfig setVolumes(BoundHostVolumes volumes) { this.volumes = volumes; return this; } 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..47a12fe9 100644 --- a/src/main/java/com/kpelykh/docker/client/model/HostConfig.java +++ b/src/main/java/com/kpelykh/docker/client/model/HostConfig.java @@ -45,6 +45,10 @@ public String[] getBinds() { public void setBinds(String[] binds) { this.binds = binds; } + + public void setBinds(final BoundHostVolumes volumes) { + setBinds(volumes.asBinds()); + } public String getContainerIDFile() { return containerIDFile; From 6b7e53ee90ec8b7a072d5584f521e62ee927fc3d Mon Sep 17 00:00:00 2001 From: getvictor Date: Sat, 15 Mar 2014 14:44:55 -0500 Subject: [PATCH 37/72] Removed "charset:UTF-8" from Content-Type. --- .../docker/client/utils/JsonClientFilter.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java b/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java index eae8d089..55b8b287 100644 --- a/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java +++ b/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java @@ -5,10 +5,6 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.filter.ClientFilter; -import javax.ws.rs.core.MediaType; -import java.util.HashMap; -import java.util.Map; - /** * * @author Konstantin Pelykh (kpelykh@gmail.com) @@ -17,12 +13,6 @@ public class JsonClientFilter extends ClientFilter { public ClientResponse handle(ClientRequest cr) { - MediaType contentType = (MediaType) cr.getHeaders().getFirst("Content-Type"); - if (contentType != null && !contentType.getParameters().containsKey("charset")) { - Map contentParams = new HashMap(); - contentParams.put("charset", "UTF-8"); - cr.getHeaders().putSingle("Content-Type", new MediaType(contentType.getType(), contentType.getSubtype(), contentParams)); - } // Call the next filter ClientResponse resp = getNext().handle(cr); String respContentType = resp.getHeaders().getFirst("Content-Type"); @@ -33,4 +23,4 @@ public ClientResponse handle(ClientRequest cr) { return resp; } -} \ No newline at end of file +} From 43eb758eb60be669190c14730aba2c9a6ba4b421 Mon Sep 17 00:00:00 2001 From: getvictor Date: Sat, 15 Mar 2014 22:09:04 +0000 Subject: [PATCH 38/72] Added supporty for copying files from container. --- .../kpelykh/docker/client/DockerClient.java | 26 ++++++++ .../docker/client/model/CopyConfig.java | 61 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100755 src/main/java/com/kpelykh/docker/client/model/CopyConfig.java diff --git a/src/main/java/com/kpelykh/docker/client/DockerClient.java b/src/main/java/com/kpelykh/docker/client/DockerClient.java index b214efb5..d29d28ee 100644 --- a/src/main/java/com/kpelykh/docker/client/DockerClient.java +++ b/src/main/java/com/kpelykh/docker/client/DockerClient.java @@ -524,6 +524,32 @@ private ClientResponse logContainer(String containerId, boolean stream) throws D } } + 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 containterDiff(String containerId) throws DockerException, NotFoundException { WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId)); diff --git a/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java new file mode 100755 index 00000000..f94106cb --- /dev/null +++ b/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java @@ -0,0 +1,61 @@ +package com.kpelykh.docker.client.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Configuration object for copy command. + * @author Victor Lyuboslavsky + */ +public class CopyConfig { + + @JsonProperty("HostPath") + private String hostPath; + + @JsonProperty("Resource") + private String resource; + + /** + * Constructor. + */ + public CopyConfig() { + hostPath = "."; + } + + /** + * Retrieves the 'resource' variable. + * @return the 'resource' variable value + */ + public String getResource() { + return resource; + } + + /** + * Sets the 'resource' variable. + * @param resource the new 'resource' variable value to set + */ + public void setResource(String resource) { + this.resource = resource; + } + + /** + * Retrieves the 'hostPath' variable. + * @return the 'hostPath' variable value + */ + public String getHostPath() { + return hostPath; + } + + /** + * Sets the 'hostPath' variable. + * @param hostPath the new 'hostPath' variable value to set + */ + public void setHostPath(String hostPath) { + this.hostPath = hostPath; + } + + @Override + public String toString() { + return "{\"HostPath\":\"" + hostPath + "\", \"Resource\":\"" + resource + "\"}"; + } + +} From 887a1120e5d3c54afa51e84f360ca6740d9916ec Mon Sep 17 00:00:00 2001 From: "alex.collins" Date: Sun, 30 Mar 2014 10:34:34 +0100 Subject: [PATCH 39/72] 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 40/72] 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 41/72] 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 42/72] 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 43/72] 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 44/72] 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 45/72] 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 46/72] 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 47/72] 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 48/72] 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 49/72] 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 50/72] 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 51/72] 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 52/72] 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 53/72] 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 54/72] 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 55/72] 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 56/72] 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 57/72] 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 58/72] 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 59/72] 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 60/72] 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 61/72] 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 62/72] 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 63/72] 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 64/72] 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 65/72] 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 66/72] 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 67/72] 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 68/72] 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 69/72] 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 70/72] 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 71/72] 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 72/72] 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