You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2015/01/14 16:49:21 UTC

[1/3] jclouds-labs git commit: support for docker 1.3.2

Repository: jclouds-labs
Updated Branches:
  refs/heads/master 590bf3e47 -> 74cefc97d


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/resources/key.pem
----------------------------------------------------------------------
diff --git a/docker/src/test/resources/key.pem b/docker/src/test/resources/key.pem
new file mode 100644
index 0000000..23ebe5e
--- /dev/null
+++ b/docker/src/test/resources/key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuUQcWlhrMXmzLSLiHUADdF98IHKRde7I1eDT91NndOtx4pKf
+vVc3WPeiREIMksrU8F1r4A086h5++xxDf27LxR4EC9ry0Q6GgJ9Un9RB9clCWRhL
+w8awHAS7HgAEN8YOSCeF3qP+78muxyMkIKQbYn3TqqOzRZcK576hX+a6URNJDhbH
+HAzq2fxmrOSRVdPXzKLl48ABfmqJ6+KiXc6e7mQSgmwBLfh51zxmJNNwZ5e+6sfZ
+8oz4yM4yKzek53GRSFj+VFNp5nS/x2072fUak2i6DGut5LibFfh1kqskIm+Iq5Ww
+O15RbojZCR6fkktCl5QOtea5p8SETZpwWfaddQIDAQABAoIBAAoj2zVqr3tGwPLQ
+fPXC4i2FaGLSQnnk9uMV6iQYUYpJtLME+W9Ajcv1ydDYmJ2UMnFxe40IzHO39ZVC
+58LaypZgXTJU6oNcuynhDp2s3WtZd6MuvD7b6hmufJtYvuJamb+DQkV8TmDLdiB6
+IOkUcldCscoeKZq+eJ9UhLqeA0aaosVUa2cfxJM2seGhF6iJmrJChvaKlc0xfqxG
+l3Y+w01YNQgFBT7vxMzfXHZkVjY8jrrsxhhfyVKiheyaBZ0G3hQCZkBywR6h2bns
+2rWM2mOcaWL7+lJiMB0d9el58HzTxFVxuPENbE2Li1SqTG1pn+Fif0VwG3Te0lPo
+xz7EL8UCgYEA3wJLL2nfVqS73yf5k2w1+uiBHK4RVHaJeQgxv1QlgeunCwOWZ0dp
+MDPQVi9CfWhEQUZKYr118V3ikecOYh+o8ruStz9fNTeA+7IXtBaE1cAbqU9ZgeS2
+vcAIfEzQmN9JtSiFsywJKLON4/aDYXGR1NZDSaXouFQ7T0F/SaL/CUsCgYEA1Kxu
+1QjOwFC1tdB/2MF9Fn7X+YWBQsdE66a5HO30FTlMmLb/ecmngB5OxvdvpfMRMQeD
+mhifSzAfnTBAzBcuz9/il6sKygfhQX6PyxtTJ5o4XlwOArkaBew8H0gBXwfAL33G
+816rNF2kCfgDJisj9iPrl+QAgrg3sJsfIwk5fD8CgYAx075eyqYHIumDM9hUsyHg
+fOCUOuROXenbbBRJbpCu1atOD7AkRVVgWsNa7lZJ1OkjOIRYSYK3ukVsWhbhn7dM
+/NIMNZGdP1iHZERdjYaCh9jmXH9gQWz/Oo/qzfLxpTo/yt0MqnMlb/DtFWBHfmua
+BYGlS/eSb+eMjtLU7iFTvwKBgDiGuFKhK6rMCPARQdnP27p97lOg23FvW28y+iKp
+UGXPu/8fLJonMgEIjTGvFJrMFzar45uyjaxDVzPFXoOgac3QmP5s9Mor/AAXboqy
+cZCmGfNijkrE/hiy6Gv8DHlAqyE0Ugvfjqu1c+M+az/a2Y0TkQvnCwezhQHIySbb
+zc6rAoGAcg9GZnYk64V2c4uzaeTekkLkZhPTv4F7xFWb0JmTurL5BR//TDDk9Oy8
+pd5VoiBnKyCRTo2oC8J8COobxJXbl5qUxEeapjtKlQeBiROWE51K2DHacD2SDgKu
+nzn5qonnU2659Aw95bfv+rGljttOu8ySZXVhs4UUKgrQvXErXhU=
+-----END RSA PRIVATE KEY-----


[3/3] jclouds-labs git commit: support for docker 1.3.2

Posted by an...@apache.org.
support for docker 1.3.2

- update value objects (Container, Config)
- add new value object (Resource, StatusCode)
- add more options for ContainerApi
- add support for pause/unpause, restart, kill, copy and attach APIs + Mock and Live tests
- add *ParseTest
- refactor MockTests
- removed *Options.NONE
- cleanup low-value javadoc
- more coverage in LiveTests
- removed useless DockerProperties
- add comments for TLS issue
- use Date where needed
- fix listImages
- add package-private constructor to value classes
- remove KillOptions, RestartOptions, StopOptions in favour of @QueryParam
- use PEM instead of PKCS12 format
- update docker/pom.xml to use sshj dependencies
- explicit usage of OkHttp driver
- simplify DockerApiMetadata
- add bouncycastle driver explicitly


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/74cefc97
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/74cefc97
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/74cefc97

Branch: refs/heads/master
Commit: 74cefc97d0d62a921bcb1635be45153037d4c233
Parents: 590bf3e
Author: Andrea Turli <an...@gmail.com>
Authored: Mon Nov 24 17:34:22 2014 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Wed Jan 14 16:48:24 2015 +0100

----------------------------------------------------------------------
 docker/README.md                                |  19 +-
 docker/pom.xml                                  |  13 +-
 .../org/jclouds/docker/DockerApiMetadata.java   |   6 +-
 .../strategy/DockerComputeServiceAdapter.java   |  18 +-
 .../docker/config/DockerHttpApiModule.java      |  22 +-
 .../config/DockerOkHttpClientSupplier.java      |  50 ++++
 .../docker/config/DockerParserModule.java       |   2 +
 .../jclouds/docker/config/DockerProperties.java |  26 --
 .../java/org/jclouds/docker/domain/Config.java  | 227 +++++++++++++-----
 .../org/jclouds/docker/domain/Container.java    | 128 ++++++----
 .../jclouds/docker/domain/ContainerSummary.java |   3 +
 .../org/jclouds/docker/domain/ExposedPorts.java |   3 +
 .../org/jclouds/docker/domain/HostConfig.java   |   3 +
 .../java/org/jclouds/docker/domain/Image.java   |  40 ++--
 .../org/jclouds/docker/domain/ImageSummary.java |  51 ++++
 .../java/org/jclouds/docker/domain/Info.java    |  49 ++--
 .../jclouds/docker/domain/NetworkSettings.java  |   3 +
 .../java/org/jclouds/docker/domain/Port.java    |   3 +
 .../org/jclouds/docker/domain/Resource.java     |  35 +++
 .../java/org/jclouds/docker/domain/State.java   |  13 +-
 .../org/jclouds/docker/domain/StatusCode.java   |  35 +++
 .../java/org/jclouds/docker/domain/Version.java |   3 +
 .../jclouds/docker/features/ContainerApi.java   | 137 +++++++++--
 .../org/jclouds/docker/features/ImageApi.java   |  27 +--
 .../org/jclouds/docker/features/MiscApi.java    |  13 +
 .../jclouds/docker/options/AttachOptions.java   | 114 +++++++++
 .../jclouds/docker/options/BuildOptions.java    |   5 -
 .../jclouds/docker/options/CommitOptions.java   |   5 -
 .../docker/options/CreateImageOptions.java      |   5 -
 .../docker/options/DeleteImageOptions.java      |  18 +-
 .../docker/options/ListContainerOptions.java    |   5 -
 .../docker/options/ListImageOptions.java        |   5 -
 .../docker/options/RemoveContainerOptions.java  |   5 -
 .../docker/suppliers/KeyStoreSupplier.java      | 130 ----------
 .../suppliers/SSLContextWithKeysSupplier.java   | 126 ++++++++--
 .../docker/compute/BaseDockerApiLiveTest.java   |   4 +-
 .../DockerComputeServiceAdapterLiveTest.java    |   6 -
 .../functions/ContainerToNodeMetadataTest.java  |   6 +-
 .../compute/functions/ImageToImageTest.java     |  31 ++-
 .../docker/features/ContainerApiLiveTest.java   |  62 ++++-
 .../docker/features/ContainerApiMockTest.java   | 236 +++++++++----------
 .../docker/features/ImageApiMockTest.java       |  59 ++---
 .../docker/features/MiscApiLiveTest.java        |  14 +-
 .../docker/features/MiscApiMockTest.java        | 107 ++-------
 .../docker/internal/BaseDockerMockTest.java     |  83 ++-----
 .../docker/internal/BaseDockerParseTest.java    |  33 +++
 .../docker/parse/ContainerParseTest.java        |  95 ++++++++
 .../docker/parse/ContainersParseTest.java       |  53 +++++
 .../jclouds/docker/parse/ImageParseTest.java    |  83 +++++++
 .../jclouds/docker/parse/ImagesParseTest.java   |  69 ++++++
 .../org/jclouds/docker/parse/InfoParseTest.java |  62 +++++
 .../jclouds/docker/parse/VersionParseTest.java  |  46 ++++
 docker/src/test/resources/cert.pem              |  22 ++
 docker/src/test/resources/image.json            |  83 +++++++
 docker/src/test/resources/images.json           |  42 ++++
 docker/src/test/resources/key.pem               |  27 +++
 56 files changed, 1798 insertions(+), 772 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/README.md
----------------------------------------------------------------------
diff --git a/docker/README.md b/docker/README.md
index 9b55cbc..e6e0d9c 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -7,10 +7,16 @@ providers, it supports the same portable abstractions offered by jclouds.
 Please follow these steps to configure your workstation for jclouds-docker:
 
 - install the latest Docker release (please visit https://docs.docker.com/installation/)
-If you are using boot2docker, notice that from version v1.3.0 the Docker daemon is set to use an encrypted TCP socket (--tls, or --tlsverify), 
-then you need to create a p12 certificate using the following command:
+
+If you are using `boot2docker`, notice that from version v1.3.0 the Docker daemon is set to use an encrypted TCP
+socket (--tls, or --tlsverify),
+then you need to import CA certificate into Trusted Certs:
       
-      `openssl pkcs12 -export -out $HOME/.jclouds/docker.p12 -inkey $HOME/.boot2docker/certs/boot2docker-vm/key.pem -in $HOME/.boot2docker/certs/boot2docker-vm/cert.pem -certfile $HOME/.boot2docker/certs/boot2docker-vm/ca.pem`
+      ` keytool -import -trustcacerts -file /Users/andrea/.boot2docker/certs/boot2docker-vm/ca.pem -alias BOOT2DOCKER -keystore $JAVA_HOME/jre/lib/security/cacerts`
+
+by default the passoword is `changeit`
+
+N.B.: From `Docker 1.3.2+` the server doesn't accept sslv3 protocol (https://github.com/docker/docker/pull/8588/files)
 
 #How it works
 
@@ -45,8 +51,9 @@ then you need to create a p12 certificate using the following command:
 As jclouds docker support is quite new, issues may occasionally arise. Please follow these steps to get things going again:
 
 1. Remove all containers
-    
-    `$ docker ps -aq | xargs docker rm -f`
+
+    $ docker rm `docker ps -a`
+
 2. remove all the images
 
-    `$ docker images -q | xargs docker rmi -f`
+    $ docker rmi -f `docker images -q`

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/pom.xml
----------------------------------------------------------------------
diff --git a/docker/pom.xml b/docker/pom.xml
index b268a83..620cae1 100644
--- a/docker/pom.xml
+++ b/docker/pom.xml
@@ -35,7 +35,7 @@
 
   <properties>
     <test.docker.endpoint>https://localhost:4243</test.docker.endpoint>
-    <test.docker.api-version>1.10</test.docker.api-version>
+    <test.docker.api-version>1.15</test.docker.api-version>
     <test.docker.identity>FIXME</test.docker.identity>
     <test.docker.credential>FIXME</test.docker.credential>
     <jclouds.osgi.export>org.jclouds.docker*;version="${project.version}"</jclouds.osgi.export>
@@ -67,7 +67,16 @@
       <groupId>org.apache.jclouds.driver</groupId>
       <artifactId>jclouds-sshj</artifactId>
       <version>${project.version}</version>
-      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-bouncycastle</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-okhttp</artifactId>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.apache.jclouds</groupId>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java b/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
index d5c470f..25d75ba 100644
--- a/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
+++ b/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
@@ -52,8 +52,6 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
 
    public static Properties defaultProperties() {
       Properties properties = BaseHttpApiMetadata.defaultProperties();
-      properties.setProperty(Constants.PROPERTY_MAX_RETRIES, "15");
-      properties.setProperty("jclouds.ssh.retry-auth", "true");
       properties.setProperty(Constants.PROPERTY_CONNECTION_TIMEOUT, "1200000"); // 15 minutes
       properties.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
       properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
@@ -66,8 +64,8 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
          super(DockerApi.class);
          id("docker")
                  .name("Docker API")
-                 .identityName("Path to Certificate .p12 file")
-                 .credentialName("Password to Certificate")
+                 .identityName("Path to certificate .pem file")
+                 .credentialName("Password to key .pem file")
                  .documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
                  .version("1.15")
                  .defaultEndpoint("https://127.0.0.1:2376")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
index 4cbb3b0..920071b 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java
@@ -40,6 +40,7 @@ import org.jclouds.docker.domain.Container;
 import org.jclouds.docker.domain.ContainerSummary;
 import org.jclouds.docker.domain.HostConfig;
 import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.domain.ImageSummary;
 import org.jclouds.docker.options.ListContainerOptions;
 import org.jclouds.docker.options.RemoveContainerOptions;
 import org.jclouds.domain.Location;
@@ -170,14 +171,13 @@ public class DockerComputeServiceAdapter implements
    @Override
    public Set<Image> listImages() {
       Set<Image> images = Sets.newHashSet();
-      for (Image image : api.getImageApi().listImages()) {
+      for (ImageSummary imageSummary : api.getImageApi().listImages()) {
          // less efficient than just listImages but returns richer json that needs repoTags coming from listImages
-         Image inspected = api.getImageApi().inspectImage(image.id());
-         if (inspected.repoTags().isEmpty()) {
-            inspected = Image.create(inspected.id(), inspected.parent(), inspected.container(), inspected.created(),
-                    inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
-                    inspected.virtualSize(), image.repoTags());
-         }
+         Image inspected = api.getImageApi().inspectImage(imageSummary.id());
+         inspected = Image.create(inspected.id(), inspected.author(), inspected.comment(), inspected.config(),
+                    inspected.containerConfig(), inspected.parent(), inspected.created(), inspected.container(),
+                 inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
+                    inspected.virtualSize(), imageSummary.repoTags());
          images.add(inspected);
       }
       return images;
@@ -237,12 +237,12 @@ public class DockerComputeServiceAdapter implements
 
    @Override
    public void resumeNode(String id) {
-      throw new UnsupportedOperationException("resume not supported");
+      api.getContainerApi().unpause(id);
    }
 
    @Override
    public void suspendNode(String id) {
-      throw new UnsupportedOperationException("suspend not supported");
+      api.getContainerApi().pause(id);
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java b/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
index ced396c..ed23d79 100644
--- a/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
+++ b/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
@@ -16,28 +16,23 @@
  */
 package org.jclouds.docker.config;
 
-import java.security.KeyStore;
-
-import javax.net.ssl.SSLContext;
-
 import org.jclouds.docker.DockerApi;
 import org.jclouds.docker.handlers.DockerErrorHandler;
-import org.jclouds.docker.suppliers.KeyStoreSupplier;
-import org.jclouds.docker.suppliers.SSLContextWithKeysSupplier;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
+import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
+import org.jclouds.http.okhttp.OkHttpClientSupplier;
+import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
 
-import com.google.common.base.Supplier;
-import com.google.inject.TypeLiteral;
-
 /**
  * Configures the Docker connection.
  */
 @ConfiguresHttpApi
+@ConfiguresHttpCommandExecutorService
 public class DockerHttpApiModule extends HttpApiModule<DockerApi> {
 
    @Override
@@ -53,11 +48,8 @@ public class DockerHttpApiModule extends HttpApiModule<DockerApi> {
    @Override
    protected void configure() {
       super.configure();
-      bind(new TypeLiteral<Supplier<SSLContext>>() {
-      }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
-      });
-      bind(new TypeLiteral<Supplier<KeyStore>>() {
-      }).to(new TypeLiteral<KeyStoreSupplier>() {
-      });
+      install(new OkHttpCommandExecutorServiceModule());
+      bind(OkHttpClientSupplier.class).to(DockerOkHttpClientSupplier.class);
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/config/DockerOkHttpClientSupplier.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/config/DockerOkHttpClientSupplier.java b/docker/src/main/java/org/jclouds/docker/config/DockerOkHttpClientSupplier.java
new file mode 100644
index 0000000..f8a29b1
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/config/DockerOkHttpClientSupplier.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.jclouds.docker.config;
+
+import org.jclouds.docker.suppliers.SSLContextWithKeysSupplier;
+import org.jclouds.http.okhttp.OkHttpClientSupplier;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.ConnectionSpec;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.TlsVersion;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+public class DockerOkHttpClientSupplier implements OkHttpClientSupplier {
+
+   private final SSLContextWithKeysSupplier sslContextWithKeysSupplier;
+
+   @Inject
+   DockerOkHttpClientSupplier(SSLContextWithKeysSupplier sslContextWithKeysSupplier) {
+      this.sslContextWithKeysSupplier = sslContextWithKeysSupplier;
+   }
+
+   @Override
+   public OkHttpClient get() {
+      OkHttpClient client = new OkHttpClient();
+      ConnectionSpec connectionSpecs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
+              .tlsVersions(TlsVersion.TLS_1_0, TlsVersion.TLS_1_1, TlsVersion.TLS_1_2)
+              .build();
+      client.setConnectionSpecs(ImmutableList.of(connectionSpecs));
+      client.setSslSocketFactory(sslContextWithKeysSupplier.get().getSocketFactory());
+      return client;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/config/DockerParserModule.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/config/DockerParserModule.java b/docker/src/main/java/org/jclouds/docker/config/DockerParserModule.java
index 70c76cb..383f99e 100644
--- a/docker/src/main/java/org/jclouds/docker/config/DockerParserModule.java
+++ b/docker/src/main/java/org/jclouds/docker/config/DockerParserModule.java
@@ -21,7 +21,9 @@ import org.jclouds.json.config.GsonModule;
 import com.google.inject.AbstractModule;
 
 public class DockerParserModule extends AbstractModule {
+
    @Override protected void configure() {
       bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/config/DockerProperties.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/config/DockerProperties.java b/docker/src/main/java/org/jclouds/docker/config/DockerProperties.java
deleted file mode 100644
index b870fea..0000000
--- a/docker/src/main/java/org/jclouds/docker/config/DockerProperties.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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 org.jclouds.docker.config;
-
-public class DockerProperties {
-
-   /**
-    * default Docker host password
-    */
-   public static final String HOST_PASSWORD = "jclouds.docker.host.password";
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Config.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Config.java b/docker/src/main/java/org/jclouds/docker/domain/Config.java
index bef8969..05dcc48 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Config.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Config.java
@@ -26,8 +26,8 @@ import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 @AutoValue
 public abstract class Config {
@@ -49,8 +49,6 @@ public abstract class Config {
 
    public abstract boolean attachStderr();
 
-   public abstract Map<String, ?> exposedPorts();
-
    public abstract boolean tty();
 
    public abstract boolean openStdin();
@@ -61,34 +59,75 @@ public abstract class Config {
 
    public abstract List<String> cmd();
 
-   public abstract List<String> dns();
+   public abstract List<String> entrypoint();
 
    public abstract String image();
 
    public abstract Map<String, ?> volumes();
 
+   @Nullable public abstract String workingDir();
+
+   public abstract boolean networkDisabled();
+
+   public abstract Map<String, ?> exposedPorts();
+
+   public abstract List<String> securityOpts();
+
+   @Nullable public abstract HostConfig hostConfig();
+
+   public abstract List<String> binds();
+
+   public abstract List<String> links();
+
+   public abstract List<Map<String, String>> lxcConf();
+
+   public abstract Map<String, List<Map<String, String>>> portBindings();
+
+   public abstract boolean publishAllPorts();
+
+   public abstract boolean privileged();
+
+   @Nullable public abstract List<String> dns();
+
+   @Nullable public abstract String dnsSearch();
+
    @Nullable public abstract String volumesFrom();
 
-   @Nullable public abstract String workingDir();
+   public abstract List<String> capAdd();
 
-   public abstract List<String> entrypoint();
+   public abstract List<String> capDrop();
 
-   public abstract boolean networkDisabled();
+   public abstract Map<String, String> restartPolicy();
 
-   public abstract List<String> onBuild();
+   @Nullable public abstract String networkMode();
+
+   public abstract Map<String, String> devices();
+
+   Config() {
+   }
 
    @SerializedNames(
-         { "Hostname", "Domainname", "User", "Memory", "MemorySwap", "CpuShares", "AttachStdin", "AttachStdout",
-               "AttachStderr", "ExposedPorts", "Tty", "OpenStdin", "StdinOnce", "Env", "Cmd", "Dns", "Image", "Volumes",
-               "VolumesFrom", "WorkingDir", "Entrypoint", "NetworkDisabled", "OnBuild" })
+         {
+                 "Hostname", "Domainname", "User", "Memory", "MemorySwap", "CpuShares", "AttachStdin", "AttachStdout",
+                 "AttachStderr", "Tty", "OpenStdin", "StdinOnce", "Env", "Cmd", "Entrypoint", "Image", "Volumes",
+                 "WorkingDir", "NetworkDisabled", "ExposedPorts", "SecurityOpts", "HostConfig", "Binds", "Links",
+                 "LxcConf", "PortBindings", "PublishAllPorts", "Privileged", "Dns", "DnsSearch", "VolumesFrom",
+                 "CapAdd", "CapDrop", "RestartPolicy", "NetworkMode", "Devices"
+         })
    public static Config create(String hostname, String domainname, String user, int memory, int memorySwap,
-         int cpuShares, boolean attachStdin, boolean attachStdout, boolean attachStderr, Map<String, ?> exposedPorts,
-         boolean tty, boolean openStdin, boolean stdinOnce, List<String> env, List<String> cmd, List<String> dns,
-         String image, Map<String, ?> volumes, String volumesFrom, String workingDir, List<String> entrypoint,
-         boolean networkDisabled, List<String> onBuild) {
-      return new AutoValue_Config(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
-            attachStderr, copyOf(exposedPorts), tty, openStdin, stdinOnce, copyOf(env), copyOf(cmd), copyOf(dns), image,
-            copyOf(volumes), volumesFrom, workingDir, copyOf(entrypoint), networkDisabled, copyOf(onBuild));
+         int cpuShares, boolean attachStdin, boolean attachStdout, boolean attachStderr, boolean tty,
+         boolean openStdin, boolean stdinOnce, List<String> env, List<String> cmd, List<String> entrypoint,
+         String image, Map<String, ?> volumes, String workingDir, boolean networkDisabled,
+         Map<String, ?> exposedPorts, List<String> securityOpts, HostConfig hostConfig, List<String> binds,
+         List<String> links, List<Map<String, String>> lxcConf, Map<String, List<Map<String, String>>> portBindings,
+         boolean publishAllPorts, boolean privileged, List<String> dns, String dnsSearch, String volumesFrom,
+         List<String> capAdd, List<String> capDrop, Map<String, String> restartPolicy, String networkMode, Map<String, String> devices) {
+      return new AutoValue_Config(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin,
+              attachStdout, attachStderr, tty, openStdin, stdinOnce, copyOf(env), copyOf(cmd), copyOf(entrypoint),
+              image, copyOf(volumes), workingDir, networkDisabled, copyOf(exposedPorts), copyOf(securityOpts), hostConfig,
+              copyOf(binds), copyOf(links), copyOf(lxcConf), copyOf(portBindings), publishAllPorts, privileged,
+              copyOf(dns), dnsSearch, volumesFrom, copyOf(capAdd), copyOf(capDrop), copyOf(restartPolicy), networkMode,
+              copyOf(devices));
    }
 
    public static Builder builder() {
@@ -109,21 +148,33 @@ public abstract class Config {
       private boolean attachStdin;
       private boolean attachStdout;
       private boolean attachStderr;
-      private Map<String, ?> exposedPorts = ImmutableMap.of();
-      private List<String> env = ImmutableList.of();
       private boolean tty;
       private boolean openStdin;
       private boolean stdinOnce;
-      private List<String> cmd = ImmutableList.of();
-      private List<String> dns = ImmutableList.of();
+      private List<String> env = Lists.newArrayList();
+      private List<String> cmd = Lists.newArrayList();
+      private List<String> entrypoint = Lists.newArrayList();
       private String image;
-      private Map<String, ?> volumes = ImmutableMap.of();
-      private String volumesFrom;
+      private Map<String, ?> volumes = Maps.newHashMap();
       private String workingDir;
-      private List<String> entrypoint = ImmutableList.of();
       private boolean networkDisabled;
-      private List<String> onBuild = ImmutableList.of();
-      private Map<String, String> restartPolicy = ImmutableMap.of();
+      private Map<String, ?> exposedPorts = Maps.newHashMap();
+      private List<String> securityOpts = Lists.newArrayList();
+      private HostConfig hostConfig;
+      private List<String> binds = Lists.newArrayList();
+      private List<String> links = Lists.newArrayList();
+      private List<Map<String, String>> lxcConf = Lists.newArrayList();
+      private Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
+      private boolean publishAllPorts;
+      private boolean privileged;
+      private List<String> dns;
+      private String dnsSearch;
+      private String volumesFrom;
+      private List<String> capAdd = Lists.newArrayList();
+      private List<String> capDrop = Lists.newArrayList();
+      private Map<String, String> restartPolicy = Maps.newHashMap();
+      private String networkMode;
+      private Map<String, String> devices = Maps.newHashMap();
 
       public Builder hostname(String hostname) {
          this.hostname = hostname;
@@ -170,11 +221,6 @@ public abstract class Config {
          return this;
       }
 
-      public Builder exposedPorts(Map<String, ?> exposedPorts) {
-         this.exposedPorts = ImmutableMap.copyOf(checkNotNull(exposedPorts, "exposedPorts"));
-         return this;
-      }
-
       public Builder tty(boolean tty) {
          this.tty = tty;
          return this;
@@ -196,22 +242,87 @@ public abstract class Config {
       }
 
       public Builder cmd(List<String> cmd) {
-         this.cmd = ImmutableList.copyOf(checkNotNull(cmd, "cmd"));
+         this.cmd = cmd;
          return this;
       }
 
-      public Builder dns(List<String> dns) {
-         this.dns = ImmutableList.copyOf(checkNotNull(dns, "dns"));
+      public Builder entrypoint(List<String> entrypoint) {
+         this.entrypoint = entrypoint;
          return this;
       }
 
       public Builder image(String image) {
-         this.image = image;
+         this.image = checkNotNull(image, "image");
          return this;
       }
 
       public Builder volumes(Map<String, ?> volumes) {
-         this.volumes = ImmutableMap.copyOf(checkNotNull(volumes, "volumes"));
+         this.volumes = volumes;
+         return this;
+      }
+
+      public Builder workingDir(String workingDir) {
+         this.workingDir = workingDir;
+         return this;
+      }
+
+      public Builder networkDisabled(boolean networkDisabled) {
+         this.networkDisabled = networkDisabled;
+         return this;
+      }
+
+      public Builder exposedPorts(Map<String, ?> exposedPorts) {
+         this.exposedPorts = exposedPorts;
+         return this;
+      }
+
+      public Builder securityOpts(List<String> securityOpts) {
+         this.securityOpts = securityOpts;
+         return this;
+      }
+
+      public Builder hostConfig(HostConfig hostConfig) {
+         this.hostConfig = checkNotNull(hostConfig, "hostConfig");
+         return this;
+      }
+
+      public Builder binds(List<String> binds) {
+         this.binds = binds;
+         return this;
+      }
+
+      public Builder links(List<String> links) {
+         this.links = links;
+         return this;
+      }
+
+      public Builder lxcConf(List<Map<String, String>> lxcConf) {
+         this.lxcConf = lxcConf;
+         return this;
+      }
+
+      public Builder portBindings(Map<String, List<Map<String, String>>> portBindings) {
+         this.portBindings = portBindings;
+         return this;
+      }
+
+      public Builder publishAllPorts(boolean publishAllPorts) {
+         this.publishAllPorts = publishAllPorts;
+         return this;
+      }
+
+      public Builder privileged(boolean privileged) {
+         this.privileged = privileged;
+         return this;
+      }
+
+      public Builder dns(List<String>  dns) {
+         this.dns = dns;
+         return this;
+      }
+
+      public Builder dnsSearch(String dnsSearch) {
+         this.dnsSearch = dnsSearch;
          return this;
       }
 
@@ -220,45 +331,49 @@ public abstract class Config {
          return this;
       }
 
-      public Builder workingDir(String workingDir) {
-         this.workingDir = workingDir;
+      public Builder capAdd(List<String> capAdd) {
+         this.capAdd = capAdd;
          return this;
       }
 
-      public Builder entrypoint(List<String> entrypoint) {
-         this.entrypoint = entrypoint;
+      public Builder capDrop(List<String> capDrop) {
+         this.capDrop = capDrop;
          return this;
       }
 
-      public Builder networkDisabled(boolean networkDisabled) {
-         this.networkDisabled = networkDisabled;
+      public Builder restartPolicy(Map<String, String> restartPolicy) {
+         this.restartPolicy = restartPolicy;
          return this;
       }
 
-      public Builder onBuild(List<String> onBuild) {
-         this.onBuild = ImmutableList.copyOf(checkNotNull(onBuild, "onBuild"));
+      public Builder networkMode(String networkMode) {
+         this.networkMode = networkMode;
          return this;
       }
 
-      public Builder restartPolicy(Map<String, String> restartPolicy) {
-         this.restartPolicy = ImmutableMap.copyOf(restartPolicy);
+      public Builder devices(Map<String, String> devices) {
+         this.devices = devices;
          return this;
       }
 
       public Config build() {
          return Config.create(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
-               attachStderr, exposedPorts, tty, openStdin, stdinOnce, env, cmd, dns, image, volumes, volumesFrom,
-               workingDir, entrypoint, networkDisabled, onBuild);
+                 attachStderr, tty, openStdin, stdinOnce, env, cmd, entrypoint, image, volumes, workingDir,
+                 networkDisabled, exposedPorts, securityOpts, hostConfig, binds, links, lxcConf, portBindings,
+                 publishAllPorts, privileged, dns, dnsSearch, volumesFrom, capAdd, capDrop, restartPolicy,
+                 networkMode, devices);
       }
 
       public Builder fromConfig(Config in) {
          return hostname(in.hostname()).domainname(in.domainname()).user(in.user()).memory(in.memory())
-               .memorySwap(in.memorySwap()).cpuShares(in.cpuShares()).attachStdin(in.attachStdin())
-               .attachStdout(in.attachStdout()).attachStderr(in.attachStderr()).exposedPorts(in.exposedPorts())
-               .tty(in.tty()).openStdin(in.openStdin()).stdinOnce(in.stdinOnce()).env(in.env()).cmd(in.cmd())
-               .dns(in.dns()).image(in.image()).volumes(in.volumes()).volumesFrom(in.volumesFrom())
-               .workingDir(in.workingDir()).entrypoint(in.entrypoint()).networkDisabled(in.networkDisabled())
-               .onBuild(in.onBuild());
+                 .memorySwap(in.memorySwap()).cpuShares(in.cpuShares()).attachStdin(in.attachStdin())
+                 .attachStdout(in.attachStdout()).attachStderr(in.attachStderr()).tty(in.tty())
+                 .image(in.image()).volumes(in.volumes()).workingDir(in.workingDir())
+                 .networkDisabled(in.networkDisabled()).exposedPorts(in.exposedPorts()).securityOpts(in.securityOpts())
+                 .hostConfig(in.hostConfig()).binds(in.binds()).links(in.links()).lxcConf(in.lxcConf())
+                 .portBindings(in.portBindings()).publishAllPorts(in.publishAllPorts()).privileged(in.privileged())
+                 .dns(in.dns()).dnsSearch(in.dnsSearch()).volumesFrom(in.volumesFrom()).capAdd(in.capAdd())
+                 .capDrop(in.capDrop()).restartPolicy(in.restartPolicy()).networkMode(in.networkMode()).devices(in.devices());
       }
 
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Container.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Container.java b/docker/src/main/java/org/jclouds/docker/domain/Container.java
index b06c3a5..e784351 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Container.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Container.java
@@ -18,6 +18,7 @@ package org.jclouds.docker.domain;
 
 import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -32,12 +33,12 @@ import com.google.common.collect.ImmutableMap;
 public abstract class Container {
    public abstract String id();
 
-   @Nullable public abstract String name();
-
-   @Nullable public abstract String created();
+   @Nullable public abstract Date created();
 
    @Nullable public abstract String path();
 
+   @Nullable public abstract String name();
+
    public abstract List<String> args();
 
    @Nullable public abstract Config config();
@@ -48,37 +49,52 @@ public abstract class Container {
 
    @Nullable public abstract NetworkSettings networkSettings();
 
+   @Nullable public abstract String sysInitPath();
+
    @Nullable public abstract String resolvConfPath();
 
+   public abstract Map<String, String> volumes();
+
+   @Nullable public abstract HostConfig hostConfig();
+
    @Nullable public abstract String driver();
 
    @Nullable public abstract String execDriver();
 
-   public abstract Map<String, String> volumes();
-
    public abstract Map<String, Boolean> volumesRW();
 
    @Nullable public abstract String command();
 
    @Nullable public abstract String status();
 
-   @Nullable public abstract HostConfig hostConfig();
-
    public abstract List<Port> ports();
 
    @Nullable public abstract String hostnamePath();
 
+   @Nullable public abstract String hostsPath();
+
+   @Nullable public abstract String mountLabel();
+
+   @Nullable public abstract String processLabel();
+
+   Container() {
+   }
+
    @SerializedNames(
-         { "Id", "Name", "Created", "Path", "Args", "Config", "State", "Image", "NetworkSettings", "ResolvConfPath",
-               "Driver", "ExecDriver", "Volumes", "VolumesRW", "Command", "Status", "HostConfig", "Ports",
-               "HostnamePath" })
-   public static Container create(String id, String name, String created, String path, List<String> args, Config config,
-         State state, String image, NetworkSettings networkSettings, String resolvConfPath, String driver,
-         String execDriver, Map<String, String> volumes, Map<String, Boolean> volumesRW, String command, String status,
-         HostConfig hostConfig, List<Port> ports, String hostnamePath) {
-      return new AutoValue_Container(id, name, created, path, copyOf(args), config, state, image, networkSettings,
-            resolvConfPath, driver, execDriver, copyOf(volumes), copyOf(volumesRW), command, status, hostConfig,
-            copyOf(ports), hostnamePath);
+         {
+                 "Id", "Created", "Path", "Name", "Args", "Config", "State", "Image", "NetworkSettings", "SysInitPath",
+                 "ResolvConfPath", "Volumes", "HostConfig", "Driver", "ExecDriver", "VolumesRW", "Command", "Status",
+                 "Ports", "HostnamePath", "HostsPath", "MountLabel", "ProcessLabel"
+         })
+   public static Container create(String id, Date created, String path, String name, List<String> args, Config config,
+                                  State state, String image, NetworkSettings networkSettings, String sysInitPath,
+                                  String resolvConfPath, Map<String, String> volumes, HostConfig hostConfig,
+                                  String driver, String execDriver, Map<String, Boolean> volumesRW, String command,
+                                  String status, List<Port> ports, String hostnamePath, String hostsPath,
+                                  String mountLabel, String processLabel) {
+      return new AutoValue_Container(id, created, path, name, copyOf(args), config, state, image, networkSettings,
+              sysInitPath, resolvConfPath, copyOf(volumes), hostConfig, driver, execDriver, copyOf(volumesRW), command,
+              status, copyOf(ports), hostnamePath, hostsPath, mountLabel, processLabel);
    }
 
    public static Builder builder() {
@@ -92,36 +108,35 @@ public abstract class Container {
    public static final class Builder {
 
       private String id;
-      private String name;
-      private String created;
+      private Date created;
       private String path;
+      private String name;
       private List<String> args;
       private Config config;
       private State state;
       private String image;
       private NetworkSettings networkSettings;
+      private String sysInitPath;
       private String resolvConfPath;
+      private Map<String, String> volumes = ImmutableMap.of();
+      private HostConfig hostConfig;
       private String driver;
       private String execDriver;
-      private Map<String, String> volumes = ImmutableMap.of();
       private Map<String, Boolean> volumesRW = ImmutableMap.of();
       private String command;
       private String status;
-      private HostConfig hostConfig;
       private List<Port> ports = ImmutableList.of();
       private String hostnamePath;
+      private String hostsPath;
+      private String mountLabel;
+      private String processLabel;
 
       public Builder id(String id) {
          this.id = id;
          return this;
       }
 
-      public Builder name(String name) {
-         this.name = name;
-         return this;
-      }
-
-      public Builder created(String created) {
+      public Builder created(Date created) {
          this.created = created;
          return this;
       }
@@ -131,6 +146,11 @@ public abstract class Container {
          return this;
       }
 
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
       public Builder args(List<String> args) {
          this.args = args;
          return this;
@@ -156,11 +176,26 @@ public abstract class Container {
          return this;
       }
 
+      public Builder sysInitPath(String sysInitPath) {
+         this.sysInitPath = sysInitPath;
+         return this;
+      }
+
       public Builder resolvConfPath(String resolvConfPath) {
          this.resolvConfPath = resolvConfPath;
          return this;
       }
 
+      public Builder volumes(Map<String, String> volumes) {
+         this.volumes = volumes;
+         return this;
+      }
+
+      public Builder hostConfig(HostConfig hostConfig) {
+         this.hostConfig = hostConfig;
+         return this;
+      }
+
       public Builder driver(String driver) {
          this.driver = driver;
          return this;
@@ -171,11 +206,6 @@ public abstract class Container {
          return this;
       }
 
-      public Builder volumes(Map<String, String> volumes) {
-         this.volumes = volumes;
-         return this;
-      }
-
       public Builder volumesRW(Map<String, Boolean> volumesRW) {
          this.volumesRW = volumesRW;
          return this;
@@ -191,11 +221,6 @@ public abstract class Container {
          return this;
       }
 
-      public Builder hostConfig(HostConfig hostConfig) {
-         this.hostConfig = hostConfig;
-         return this;
-      }
-
       public Builder ports(List<Port> ports) {
          this.ports = ports;
          return this;
@@ -206,17 +231,34 @@ public abstract class Container {
          return this;
       }
 
+      public Builder hostsPath(String hostsPath) {
+         this.hostsPath = hostsPath;
+         return this;
+      }
+
+      public Builder mountLabel(String mountLabel) {
+         this.mountLabel = mountLabel;
+         return this;
+      }
+
+      public Builder processLabel(String processLabel) {
+         this.processLabel = processLabel;
+         return this;
+      }
+
       public Container build() {
-         return Container.create(id, name, created, path, args, config, state, image, networkSettings, resolvConfPath,
-                 driver, execDriver, volumes, volumesRW, command, status, hostConfig, ports, hostnamePath);
+         return Container.create(id, created, path, name, args, config, state, image, networkSettings,
+                 sysInitPath, resolvConfPath, volumes, hostConfig, driver, execDriver, volumesRW, command, status,
+                 ports, hostnamePath, hostsPath, mountLabel, processLabel);
       }
 
       public Builder fromContainer(Container in) {
          return this.id(in.id()).name(in.name()).created(in.created()).path(in.path()).args(in.args())
-               .config(in.config()).state(in.state()).image(in.image()).networkSettings(in.networkSettings())
-               .resolvConfPath(in.resolvConfPath()).driver(in.driver()).execDriver(in.execDriver())
-               .volumes(in.volumes()).volumesRW(in.volumesRW()).command(in.command()).status(in.status())
-               .hostConfig(in.hostConfig()).ports(in.ports()).hostnamePath(in.hostnamePath());
+                 .config(in.config()).state(in.state()).image(in.image()).networkSettings(in.networkSettings())
+                 .sysInitPath(in.sysInitPath()).resolvConfPath(in.resolvConfPath()).driver(in.driver())
+                 .execDriver(in.execDriver()).volumes(in.volumes()).hostConfig(in.hostConfig()).volumesRW(in.volumesRW())
+                 .command(in.command()).status(in.status()).ports(in.ports()).hostnamePath(in.hostnamePath())
+                 .hostsPath(in.hostsPath()).mountLabel(in.mountLabel()).processLabel(in.processLabel());
       }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java b/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java
index 17d0064..25bd595 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java
@@ -41,6 +41,9 @@ public abstract class ContainerSummary {
 
    public abstract String status();
 
+   ContainerSummary() {
+   }
+
    @SerializedNames({"Id", "Names", "Created", "Image", "Command", "Ports", "Status"})
    public static ContainerSummary create(String id, List<String> names, String created, String image, String command, List<Port> ports, String status) {
       return new AutoValue_ContainerSummary(id, copyOf(names), created, image, command, copyOf(ports), status);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/ExposedPorts.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/ExposedPorts.java b/docker/src/main/java/org/jclouds/docker/domain/ExposedPorts.java
index 413c84f..ac57a98 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/ExposedPorts.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/ExposedPorts.java
@@ -30,6 +30,9 @@ public abstract class ExposedPorts {
 
    public abstract List<String> hostPorts();
 
+   ExposedPorts() {
+   }
+
    @SerializedNames({ "PortAndProtocol", "HostPorts" })
    public static ExposedPorts create(String portAndProtocol, List<String> hostPorts) {
       return new AutoValue_ExposedPorts(portAndProtocol, copyOf(hostPorts));

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java b/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
index 630be7c..30efd9c 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
@@ -51,6 +51,9 @@ public abstract class HostConfig {
 
    public abstract List<String> volumesFrom();
 
+   HostConfig() {
+   }
+
    @SerializedNames({ "ContainerIDFile", "Binds", "LxcConf", "Privileged", "Dns", "DnsSearch", "PortBindings",
            "Links", "PublishAllPorts", "VolumesFrom" })
    public static HostConfig create(String containerIDFile, List<String> binds, List<Map<String, String>> lxcConf,

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Image.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Image.java b/docker/src/main/java/org/jclouds/docker/domain/Image.java
index c80e448..f49a7b0 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Image.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Image.java
@@ -18,6 +18,7 @@ package org.jclouds.docker.domain;
 
 import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
 
+import java.util.Date;
 import java.util.List;
 
 import org.jclouds.javax.annotation.Nullable;
@@ -27,32 +28,43 @@ import com.google.auto.value.AutoValue;
 
 @AutoValue
 public abstract class Image {
+
    public abstract String id();
 
-   @Nullable public abstract String parent();
+   @Nullable public abstract String author();
+
+   @Nullable public abstract String comment();
+
+   @Nullable public abstract Config config();
+
+   @Nullable public abstract Config containerConfig();
 
-   @Nullable public abstract String created();
+   public abstract String parent();
 
-   @Nullable public abstract String container();
+   public abstract Date created();
 
-   @Nullable public abstract String dockerVersion();
+   public abstract String container();
 
-   @Nullable public abstract String architecture();
+   public abstract String dockerVersion();
 
-   @Nullable public abstract String os();
+   public abstract String architecture();
+
+   public abstract String os();
 
    public abstract long size();
 
-   @Nullable public abstract long virtualSize();
+   public abstract long virtualSize();
+
+   @Nullable public abstract List<String> repoTags();
 
-   public abstract List<String> repoTags();
+   Image() {
+   }
 
-   @SerializedNames({ "Id", "Parent", "Created", "Container", "DockerVersion", "Architecture", "Os", "Size",
-         "VirtualSize", "RepoTags" })
-   public static Image create(String id, String parent, String created, String container, String dockerVersion,
-         String architecture, String os, long size, long virtualSize, List<String> repoTags) {
-      return new AutoValue_Image(id, parent, created, container, dockerVersion, architecture, os, size, virtualSize,
-            copyOf(repoTags));
+   @SerializedNames({ "Id", "Author", "Comment", "Config", "ContainerConfig", "Parent", "Created",
+           "Container", "DockerVersion", "Architecture", "Os", "Size", "VirtualSize", "RepoTags" })
+   public static Image create(String id, String author, String comment, Config config, Config containerConfig, String parent, Date created, String container, String dockerVersion, String architecture, String os, long size, long virtualSize, List<String> repoTags) {
+      return new AutoValue_Image(id, author, comment, config, containerConfig, parent, created, container,
+              dockerVersion, architecture, os, size, virtualSize, copyOf(repoTags));
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/ImageSummary.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/ImageSummary.java b/docker/src/main/java/org/jclouds/docker/domain/ImageSummary.java
new file mode 100644
index 0000000..f4ea9b9
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/domain/ImageSummary.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.jclouds.docker.domain;
+
+import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
+import java.util.List;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+// TODO it may be redundant (we already have Image value class)
+@AutoValue
+public abstract class ImageSummary {
+
+   public abstract String id();
+
+   public abstract long created();
+
+   public abstract String parentId();
+
+   public abstract int size();
+
+   public abstract int virtualSize();
+
+   public abstract List<String> repoTags();
+
+   ImageSummary() {
+   }
+
+   @SerializedNames({"Id", "Created", "ParentId", "Size", "VirtualSize", "RepoTags"})
+   public static ImageSummary create(String id, long created, String parentId, int size, int virtualSize,
+                                     List<String> repoTags) {
+      return new AutoValue_ImageSummary(id, created, parentId, size, virtualSize, copyOf(repoTags));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Info.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Info.java b/docker/src/main/java/org/jclouds/docker/domain/Info.java
index 596c0a5..8a4c504 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Info.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Info.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.docker.domain;
 
+import java.util.List;
+
 import org.jclouds.json.SerializedNames;
 
 import com.google.auto.value.AutoValue;
@@ -25,39 +27,52 @@ public abstract class Info {
 
    public abstract int containers();
 
-   public abstract int images();
+   public abstract int debug();
 
    public abstract String driver();
 
+   public abstract List<List<String>> driverStatus();
+
    public abstract String executionDriver();
 
-   public abstract String kernelVersion();
+   public abstract int iPv4Forwarding();
 
-   public abstract int debug();
+   public abstract int images();
 
-   public abstract int nFd();
+   public abstract String indexServerAddress();
 
-   public abstract int nGoroutines();
+   public abstract String initPath();
+
+   public abstract String initSha1();
+
+   public abstract String kernelVersion();
+
+   public abstract int memoryLimit();
 
    public abstract int nEventsListener();
 
-   public abstract String initPath();
+   public abstract int nFd();
 
-   public abstract String indexServerAddress();
+   public abstract int nGoroutines();
 
-   public abstract int memoryLimit();
+   public abstract String operatingSystem();
 
    public abstract int swapLimit();
 
-   public abstract int iPv4Forwarding();
+   Info() {
+   }
 
-   @SerializedNames(
-           {"Containers", "Images", "Driver", "ExecutionDriver", "KernelVersion", "Debug", "NFd", "NGoroutines",
-                   "NEventsListener", "InitPath", "IndexServerAddress", "MemoryLimit", "SwapLimit", "IPv4Forwarding"})
-   public static Info create(int containers, int images, String driver, String executionDriver, String kernelVersion, int debug,
-                             int nFd, int nGoroutines, int nEventsListener, String initPath, String indexServerAddress,
-                             int memoryLimit, int swapLimit, int iPv4Forwarding) {
-      return new AutoValue_Info(containers, images, driver, executionDriver, kernelVersion, debug, nFd, nGoroutines,
-              nEventsListener, initPath, indexServerAddress, memoryLimit, swapLimit, iPv4Forwarding);
+   @SerializedNames({
+                   "Containers", "Debug", "Driver", "DriverStatus", "ExecutionDriver", "IPv4Forwarding", "Images",
+                   "IndexServerAddress", "InitPath", "InitSha1", "KernelVersion", "MemoryLimit", "NEventsListener",
+                   "NFd", "NGoroutines", "OperatingSystem", "SwapLimit"
+   })
+   public static Info create(int containers, int debug, String driver, List<List<String>> driverStatus,
+                             String executionDriver, int iPv4Forwarding, int images, String indexServerAddress,
+                             String initPath, String initSha1, String kernelVersion, int memoryLimit,
+                             int nEventsListener, int nFd, int nGoroutines, String operatingSystem, int swapLimit) {
+      return new AutoValue_Info(containers, debug, driver, driverStatus, executionDriver, iPv4Forwarding, images,
+              indexServerAddress, initPath, initSha1, kernelVersion, memoryLimit, nEventsListener, nFd, nGoroutines,
+              operatingSystem, swapLimit);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/NetworkSettings.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/NetworkSettings.java b/docker/src/main/java/org/jclouds/docker/domain/NetworkSettings.java
index f99bd7f..fee82f2 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/NetworkSettings.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/NetworkSettings.java
@@ -42,6 +42,9 @@ public abstract class NetworkSettings {
 
    public abstract Map<String, List<Map<String, String>>> ports();
 
+   NetworkSettings() {
+   }
+
    @SerializedNames({ "IPAddress", "IPPrefixLen", "Gateway", "Bridge", "PortMapping", "Ports" })
    public static NetworkSettings create(String ipAddress, int ipPrefixLen, String gateway, String bridge,
          String portMapping, Map<String, List<Map<String, String>>> ports) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Port.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Port.java b/docker/src/main/java/org/jclouds/docker/domain/Port.java
index 0522be1..b4bc93e 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Port.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Port.java
@@ -30,6 +30,9 @@ public abstract class Port {
 
    public abstract String type();
 
+   Port() {
+   }
+
    @SerializedNames({ "IP", "PrivatePort", "PublicPort", "Type" })
    public static Port create(String ip, int privatePort, int publicPort, String type) {
       return new AutoValue_Port(ip, privatePort, publicPort, type);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Resource.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Resource.java b/docker/src/main/java/org/jclouds/docker/domain/Resource.java
new file mode 100644
index 0000000..701318c
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/domain/Resource.java
@@ -0,0 +1,35 @@
+/*
+ * 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 org.jclouds.docker.domain;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Resource {
+
+   public abstract String resource();
+
+   Resource() {
+   }
+
+   @SerializedNames({ "Resource" })
+   public static Resource create(String resource) {
+      return new AutoValue_Resource(resource);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/State.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/State.java b/docker/src/main/java/org/jclouds/docker/domain/State.java
index c0a8586..1b3c809 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/State.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/State.java
@@ -32,11 +32,16 @@ public abstract class State {
 
    public abstract String finishedAt();
 
-   public abstract boolean ghost();
+   public abstract boolean paused();
 
-   @SerializedNames({ "Pid", "Running", "ExitCode", "StartedAt", "FinishedAt", "Ghost" })
+   public abstract boolean restarting();
+
+   State() {
+   }
+
+   @SerializedNames({ "Pid", "Running", "ExitCode", "StartedAt", "FinishedAt", "Paused", "Restarting" })
    public static State create(int pid, boolean running, int exitCode, String startedAt, String finishedAt,
-         boolean ghost) {
-      return new AutoValue_State(pid, running, exitCode, startedAt, finishedAt, ghost);
+         boolean paused, boolean restarting) {
+      return new AutoValue_State(pid, running, exitCode, startedAt, finishedAt, paused, restarting);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/StatusCode.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/StatusCode.java b/docker/src/main/java/org/jclouds/docker/domain/StatusCode.java
new file mode 100644
index 0000000..0bdfdc7
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/domain/StatusCode.java
@@ -0,0 +1,35 @@
+/*
+ * 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 org.jclouds.docker.domain;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class StatusCode {
+
+   public abstract int statusCode();
+
+   StatusCode() {
+   }
+
+   @SerializedNames({ "StatusCode" })
+   public static StatusCode create(int statusCode) {
+      return new AutoValue_StatusCode(statusCode);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/domain/Version.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/domain/Version.java b/docker/src/main/java/org/jclouds/docker/domain/Version.java
index 7cf7960..9002d41 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Version.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Version.java
@@ -37,6 +37,9 @@ public abstract class Version {
 
    public abstract String version();
 
+   Version() {
+   }
+
    @SerializedNames({ "ApiVersion", "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
    public static Version create(String apiVersion, String arch, String gitCommit, String goVersion,
                                 String kernelVersion, String os, String version) {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java b/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java
index 60f7749..fb592c8 100644
--- a/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java
+++ b/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.docker.features;
 
+import java.io.InputStream;
 import java.util.List;
 
 import javax.inject.Named;
@@ -28,12 +29,16 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
-import org.jclouds.Fallbacks;
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.docker.domain.Config;
 import org.jclouds.docker.domain.Container;
 import org.jclouds.docker.domain.ContainerSummary;
 import org.jclouds.docker.domain.HostConfig;
 import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.domain.Resource;
+import org.jclouds.docker.domain.StatusCode;
+import org.jclouds.docker.options.AttachOptions;
 import org.jclouds.docker.options.CommitOptions;
 import org.jclouds.docker.options.ListContainerOptions;
 import org.jclouds.docker.options.RemoveContainerOptions;
@@ -42,34 +47,29 @@ import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
 @Consumes(MediaType.APPLICATION_JSON)
+@Path("/v{jclouds.api-version}")
 public interface ContainerApi {
 
    /**
-    * List all running containers
-    *
     * @return a set of containers
     */
    @Named("containers:list")
    @GET
    @Path("/containers/json")
-   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   @Fallback(EmptyListOnNotFoundOr404.class)
    List<ContainerSummary> listContainers();
 
    /**
-    * List all running containers
-    *
     * @param options the options to list the containers (@see ListContainerOptions)
     * @return a set of containers
     */
    @Named("containers:list")
    @GET
    @Path("/containers/json")
-   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   @Fallback(EmptyListOnNotFoundOr404.class)
    List<ContainerSummary> listContainers(ListContainerOptions options);
 
    /**
-    * Create a container
-    *
     * @param name the name for the new container. Must match /?[a-zA-Z0-9_-]+.
     * @param config the container’s configuration (@see BindToJsonPayload)
     * @return a new container
@@ -87,12 +87,10 @@ public interface ContainerApi {
    @Named("container:inspect")
    @GET
    @Path("/containers/{id}/json")
-   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   @Fallback(NullOnNotFoundOr404.class)
    Container inspectContainer(@PathParam("id") String containerId);
 
    /**
-    * Remove the container by id from the filesystem
-    *
     * @param containerId The id of the container to be removed.
     */
    @Named("container:delete")
@@ -101,8 +99,6 @@ public interface ContainerApi {
    void removeContainer(@PathParam("id") String containerId);
 
    /**
-    * Remove the container by id from the filesystem
-    *
     * @param containerId The id of the container to be removed.
     * @param options the operation’s configuration (@see RemoveContainerOptions)
     */
@@ -112,8 +108,6 @@ public interface ContainerApi {
    void removeContainer(@PathParam("id") String containerId, RemoveContainerOptions options);
 
    /**
-    * Start a container by id.
-    *
     * @param containerId The id of the container to be started.
     */
    @Named("container:start")
@@ -122,8 +116,6 @@ public interface ContainerApi {
    void startContainer(@PathParam("id") String containerId);
 
    /**
-    * Start a container.
-    *
     * @param containerId The id of the container to be started.
     * @param hostConfig the container’s host configuration
     */
@@ -133,16 +125,28 @@ public interface ContainerApi {
    void startContainer(@PathParam("id") String containerId, @BinderParam(BindToJsonPayload.class) HostConfig hostConfig);
 
    /**
-    * Stop a container by id.
-    *
     * @param containerId The id of the container to be stopped.
-    * @return the stream of the stop execution.
     */
    @Named("container:stop")
    @POST
    @Path("/containers/{id}/stop")
    void stopContainer(@PathParam("id") String containerId);
 
+   @Named("container:stop")
+   @POST
+   @Path("/containers/{id}/stop")
+   void stopContainer(@PathParam("id") String containerId, @QueryParam("t") int secondsToWait);
+
+   /**
+    * Create a new image from a container’s changes
+    *
+    * @return a new image created from the current container's status.
+    */
+   @Named("container:commit")
+   @POST
+   @Path("/commit")
+   Image commit();
+
    /**
     * Create a new image from a container’s changes
     *
@@ -154,4 +158,95 @@ public interface ContainerApi {
    @Path("/commit")
    Image commit(CommitOptions options);
 
+   /**
+    * @param containerId The id of the container to be paused.
+    */
+   @Named("container:pause")
+   @POST
+   @Path("/containers/{id}/pause")
+   void pause(@PathParam("id") String containerId);
+
+   /**
+    * @param containerId The id of the container to be unpaused.
+    */
+   @Named("container:unpause")
+   @POST
+   @Path("/containers/{id}/unpause")
+   void unpause(@PathParam("id") String containerId);
+
+   /**
+    * @param containerId The id of the container to be attached.
+    */
+   @Named("container:attach")
+   @POST
+   @Path("/containers/{id}/attach")
+   InputStream attach(@PathParam("id") String containerId);
+
+   /**
+    * @param containerId The id of the container to be attached.
+    * @param options the attach options @see org.jclouds.docker.options.AttachOptions
+    *
+    */
+   @Named("container:attach")
+   @POST
+   @Path("/containers/{id}/attach")
+   InputStream attach(@PathParam("id") String containerId, AttachOptions options);
+
+   /**
+    * Block until container @param containerId stops, then returns the exit code
+    */
+   @Named("container:wait")
+   @POST
+   @Path("/containers/{id}/wait")
+   StatusCode wait(@PathParam("id") String containerId);
+
+   /**
+    * @param containerId restarts
+    */
+   @Named("container:restart")
+   @POST
+   @Path("/containers/{id}/restart")
+   void restart(@PathParam("id") String containerId);
+
+   @Named("container:restart")
+   @POST
+   @Path("/containers/{id}/restart")
+   void restart(@PathParam("id") String containerId, @QueryParam("t") int secondsToWait);
+
+
+   /**
+    * @param containerId to be killed
+    */
+   @Named("container:kill")
+   @POST
+   @Path("/containers/{id}/kill")
+   void kill(@PathParam("id") String containerId);
+
+   /**
+    * @param containerId to be killed
+    * @param signal Signal to send to the container. When not set, SIGKILL is assumed and the call will waits for the
+    *               container to exit.
+    */
+   @Named("container:kill")
+   @POST
+   @Path("/containers/{id}/kill")
+   void kill(@PathParam("id") String containerId, @QueryParam("signal") int signal);
+
+   /**
+    * @param containerId to be killed
+    * @param signal Signal string like "SIGINT" to send to the container. When not set, SIGKILL is assumed and the call will waits for
+    *               the container to exit.
+    */
+   @Named("container:kill")
+   @POST
+   @Path("/containers/{id}/kill")
+   void kill(@PathParam("id") String containerId, @QueryParam("signal") String signal);
+
+   /**
+    * @param containerId id of the container to copy files from
+    */
+   @Named("container:copy")
+   @POST
+   @Path("/containers/{id}/copy")
+   InputStream copy(@PathParam("id") String containerId, @BinderParam(BindToJsonPayload.class) Resource resource);
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/features/ImageApi.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/features/ImageApi.java b/docker/src/main/java/org/jclouds/docker/features/ImageApi.java
index 95c963c..9f7cebc 100644
--- a/docker/src/main/java/org/jclouds/docker/features/ImageApi.java
+++ b/docker/src/main/java/org/jclouds/docker/features/ImageApi.java
@@ -28,49 +28,48 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
 
-import org.jclouds.Fallbacks;
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.domain.ImageSummary;
 import org.jclouds.docker.options.CreateImageOptions;
 import org.jclouds.docker.options.DeleteImageOptions;
 import org.jclouds.docker.options.ListImageOptions;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.annotations.Fallback;
 
 @Consumes(MediaType.APPLICATION_JSON)
+@Path("/v{jclouds.api-version}")
 public interface ImageApi {
 
    /**
-    * List images
-    *
     * @return the images available.
     */
    @Named("images:list")
    @GET
    @Path("/images/json")
-   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
-   List<Image> listImages();
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<ImageSummary> listImages();
 
    /**
-    * List images
-    *
     * @param options the configuration to list images (@see ListImageOptions)
     * @return the images available.
     */
    @Named("images:list")
    @GET
    @Path("/images/json")
-   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
-   List<Image> listImages(ListImageOptions options);
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<ImageSummary> listImages(ListImageOptions options);
 
    /**
-    * Inspect an image
-    *
     * @param imageName The id of the image to inspect.
     * @return low-level information on the image name
     */
    @Named("image:inspect")
    @GET
    @Path("/images/{name}/json")
-   @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
    Image inspectImage(@PathParam("name") String imageName);
 
    /**
@@ -85,8 +84,6 @@ public interface ImageApi {
    InputStream createImage(CreateImageOptions options);
 
    /**
-    * Delete an image.
-    *
     * @param name the image name to be deleted
     * @return the stream of the deletion execution.
     */
@@ -96,8 +93,6 @@ public interface ImageApi {
    InputStream deleteImage(@PathParam("name") String name);
 
    /**
-    * Remove the image from the filesystem by name
-    *
     * @param name the name of the image to be removed
     * @param options the image deletion's options (@see DeleteImageOptions)
     * @return the stream of the deletion execution.

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/features/MiscApi.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/features/MiscApi.java b/docker/src/main/java/org/jclouds/docker/features/MiscApi.java
index 30cd1f3..6c49436 100644
--- a/docker/src/main/java/org/jclouds/docker/features/MiscApi.java
+++ b/docker/src/main/java/org/jclouds/docker/features/MiscApi.java
@@ -32,6 +32,7 @@ import org.jclouds.io.Payload;
 import org.jclouds.rest.annotations.Headers;
 
 @Consumes(MediaType.APPLICATION_JSON)
+@Path("/v{jclouds.api-version}")
 public interface MiscApi {
 
    /**
@@ -54,6 +55,18 @@ public interface MiscApi {
    @Path("/info")
    Info getInfo();
 
+   /**
+    * Build an image from Dockerfile via stdin
+    *
+    * @param inputStream The stream must be a tar archive compressed with one of the following algorithms: identity
+    *                    (no compression), gzip, bzip2, xz.
+    * @return a stream of the build execution
+    */
+   @Named("image:build")
+   @POST
+   @Path("/build")
+   @Headers(keys = "Content-Type", values = "application/tar")
+   InputStream build(Payload inputStream);
 
    /**
     * Build an image from Dockerfile via stdin

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/AttachOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/AttachOptions.java b/docker/src/main/java/org/jclouds/docker/options/AttachOptions.java
new file mode 100644
index 0000000..95fb8b5
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/options/AttachOptions.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.jclouds.docker.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class AttachOptions extends BaseHttpRequestOptions {
+
+   /**
+    * @param stream When TTY is enabled, the stream is the raw data from the process PTY and client's stdin.
+    *               When TTY is disabled, the stream is multiplexed to separate stdout and stderr.
+    * @return AttachOptions
+    */
+   public AttachOptions stream(Boolean stream) {
+      this.queryParameters.put("stream", stream.toString());
+      return this;
+   }
+
+   /**
+    * @param logs require logs to be attached. Default false.
+    * @return AttachOptions
+    */
+   public AttachOptions logs(Boolean logs) {
+      this.queryParameters.put("logs", logs.toString());
+      return this;
+   }
+
+   /**
+    * @param stdin if stream=true, attach to stdin. Default false
+    * @return AttachOptions
+    */
+   public AttachOptions stdin(Boolean stdin) {
+      this.queryParameters.put("stdin", stdin.toString());
+      return this;
+   }
+
+   /**
+    * @param stdout if logs=true, return stdout log, if stream=true, attach to stdout. Default false
+    * @return
+    */
+   public AttachOptions stdout(Boolean stdout) {
+      this.queryParameters.put("stdout", stdout.toString());
+      return this;
+   }
+
+   /**
+    *
+    * @param stderr if logs=true, return stderr log, if stream=true, attach to stderr. Default false
+    * @return
+    */
+   public AttachOptions stderr(Boolean stderr) {
+      this.queryParameters.put("stderr", stderr.toString());
+      return this;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see org.jclouds.docker.options.AttachOptions#stream
+       */
+      public static AttachOptions stream(Boolean stream) {
+         AttachOptions options = new AttachOptions();
+         return options.stream(stream);
+      }
+
+      /**
+       * @see org.jclouds.docker.options.AttachOptions#logs(Boolean)
+       */
+      public static AttachOptions logs(Boolean logs) {
+         AttachOptions options = new AttachOptions();
+         return options.logs(logs);
+      }
+
+      /**
+       * @see org.jclouds.docker.options.AttachOptions#stdin(Boolean)
+       */
+      public static AttachOptions stdin(Boolean stdin) {
+         AttachOptions options = new AttachOptions();
+         return options.stdin(stdin);
+      }
+
+      /**
+       * @see org.jclouds.docker.options.AttachOptions#stdout(Boolean)
+       */
+      public static AttachOptions stdout(Boolean stdout) {
+         AttachOptions options = new AttachOptions();
+         return options.stdout(stdout);
+      }
+
+      /**
+       * @see org.jclouds.docker.options.AttachOptions#stderr(Boolean)
+       */
+      public static AttachOptions stderr(Boolean stderr) {
+         AttachOptions options = new AttachOptions();
+         return options.stderr(stderr);
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/BuildOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/BuildOptions.java b/docker/src/main/java/org/jclouds/docker/options/BuildOptions.java
index 4d7196c..14bc4a4 100644
--- a/docker/src/main/java/org/jclouds/docker/options/BuildOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/BuildOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize image builder.
- */
 public class BuildOptions extends BaseHttpRequestOptions {
 
-   public static final BuildOptions NONE = new BuildOptions();
-
    public BuildOptions tag(String tag) {
       this.queryParameters.put("tag", tag);
       return this;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/CommitOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/CommitOptions.java b/docker/src/main/java/org/jclouds/docker/options/CommitOptions.java
index 5653fba..fbf35b6 100644
--- a/docker/src/main/java/org/jclouds/docker/options/CommitOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/CommitOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize image commit.
- */
 public class CommitOptions extends BaseHttpRequestOptions {
 
-   public static final CommitOptions NONE = new CommitOptions();
-
    public CommitOptions containerId(String containerId) {
       this.queryParameters.put("containerId", containerId);
       return this;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/CreateImageOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/CreateImageOptions.java b/docker/src/main/java/org/jclouds/docker/options/CreateImageOptions.java
index 51dc399..91b8413 100644
--- a/docker/src/main/java/org/jclouds/docker/options/CreateImageOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/CreateImageOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize container creation.
- */
 public class CreateImageOptions extends BaseHttpRequestOptions {
 
-   public static final CreateImageOptions NONE = new CreateImageOptions();
-
    public CreateImageOptions fromImage(String fromImage) {
       this.queryParameters.put("fromImage", fromImage);
       return this;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/DeleteImageOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/DeleteImageOptions.java b/docker/src/main/java/org/jclouds/docker/options/DeleteImageOptions.java
index 9438616..1ac20d9 100644
--- a/docker/src/main/java/org/jclouds/docker/options/DeleteImageOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/DeleteImageOptions.java
@@ -18,18 +18,18 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize image deletion.
- */
 public class DeleteImageOptions extends BaseHttpRequestOptions {
 
-   public static final DeleteImageOptions NONE = new DeleteImageOptions();
-
    public DeleteImageOptions force(Boolean force) {
       this.queryParameters.put("force", force.toString());
       return this;
    }
 
+   public DeleteImageOptions noPrune(Boolean noPrune) {
+      this.queryParameters.put("noPrune", noPrune.toString());
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -39,6 +39,14 @@ public class DeleteImageOptions extends BaseHttpRequestOptions {
          DeleteImageOptions options = new DeleteImageOptions();
          return options.force(force);
       }
+
+      /**
+       * @see DeleteImageOptions#noPrune
+       */
+      public static DeleteImageOptions noPrune(Boolean noPrune) {
+         DeleteImageOptions options = new DeleteImageOptions();
+         return options.noPrune(noPrune);
+      }
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/ListContainerOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/ListContainerOptions.java b/docker/src/main/java/org/jclouds/docker/options/ListContainerOptions.java
index af16664..7f73804 100644
--- a/docker/src/main/java/org/jclouds/docker/options/ListContainerOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/ListContainerOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize container's listing.
- */
 public class ListContainerOptions extends BaseHttpRequestOptions {
 
-   public static final ListContainerOptions NONE = new ListContainerOptions();
-
    public ListContainerOptions all(Boolean all) {
       this.queryParameters.put("all", all.toString());
       return this;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/ListImageOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/ListImageOptions.java b/docker/src/main/java/org/jclouds/docker/options/ListImageOptions.java
index fab75d4..613eff6 100644
--- a/docker/src/main/java/org/jclouds/docker/options/ListImageOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/ListImageOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize image's listing.
- */
 public class ListImageOptions extends BaseHttpRequestOptions {
 
-   public static final ListImageOptions NONE = new ListImageOptions();
-
    public ListImageOptions all(Boolean all) {
       this.queryParameters.put("all", all.toString());
       return this;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/options/RemoveContainerOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/options/RemoveContainerOptions.java b/docker/src/main/java/org/jclouds/docker/options/RemoveContainerOptions.java
index 5c3abba..9334e69 100644
--- a/docker/src/main/java/org/jclouds/docker/options/RemoveContainerOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/options/RemoveContainerOptions.java
@@ -18,13 +18,8 @@ package org.jclouds.docker.options;
 
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
-/**
- * Options to customize container removal.
- */
 public class RemoveContainerOptions extends BaseHttpRequestOptions {
 
-   public static final RemoveContainerOptions NONE = new RemoveContainerOptions();
-
    public RemoveContainerOptions verbose(Boolean verbose) {
       this.queryParameters.put("verbose", verbose.toString());
       return this;


[2/3] jclouds-labs git commit: support for docker 1.3.2

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/suppliers/KeyStoreSupplier.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/suppliers/KeyStoreSupplier.java b/docker/src/main/java/org/jclouds/docker/suppliers/KeyStoreSupplier.java
deleted file mode 100644
index e8643cd..0000000
--- a/docker/src/main/java/org/jclouds/docker/suppliers/KeyStoreSupplier.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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 org.jclouds.docker.suppliers;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Throwables.propagate;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.util.Collection;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.jclouds.crypto.Crypto;
-import org.jclouds.crypto.Pems;
-import org.jclouds.domain.Credentials;
-import org.jclouds.location.Provider;
-import org.jclouds.rest.AuthorizationException;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Supplier;
-import com.google.common.io.ByteSource;
-
-@Singleton
-public class KeyStoreSupplier implements Supplier<KeyStore> {
-   private final Crypto crypto;
-   private final Supplier<Credentials> creds;
-
-   @Inject
-   KeyStoreSupplier(Crypto crypto, @Provider Supplier<Credentials> creds) {
-      this.crypto = crypto;
-      this.creds = creds;
-   }
-
-   @Override
-   public KeyStore get() {
-      Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
-      String cert = checkNotNull(currentCreds.identity, "credential supplier returned null identity (should be cert)");
-      String keyStorePassword = checkNotNull(currentCreds.credential,
-            "credential supplier returned null credential (should be keyStorePassword)");
-      try {
-         KeyStore keyStore = KeyStore.getInstance("PKCS12");
-
-         File certFile = new File(checkNotNull(cert));
-         if (certFile.isFile()) { // cert is path to pkcs12 file
-            FileInputStream stream = new FileInputStream(certFile);
-            try {
-               keyStore.load(stream, keyStorePassword.toCharArray());
-            } finally {
-               stream.close();
-            }
-         } else { // cert is PEM encoded, containing private key and certs
-
-            // split in private key and certs
-            int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
-            int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
-            if (privateKeyBeginIdx != -1) {
-               String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
-
-               StringBuilder pemCerts = new StringBuilder();
-               int certsBeginIdx = 0;
-
-               do {
-                  certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
-
-                  if (certsBeginIdx >= 0) {
-                     int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
-                     pemCerts.append(cert.substring(certsBeginIdx, certsEndIdx));
-                     certsBeginIdx = certsEndIdx;
-                  }
-               } while (certsBeginIdx != -1);
-
-               // parse private key
-               KeySpec keySpec = Pems.privateKeySpec(ByteSource.wrap(pemPrivateKey.getBytes(Charsets.UTF_8)));
-               PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
-
-               // populate keystore with private key and certs
-               CertificateFactory cf = CertificateFactory.getInstance("X.509");
-               @SuppressWarnings("unchecked")
-               Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
-                       pemCerts.toString().getBytes(Charsets.UTF_8)));
-               keyStore.load(null);
-               keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
-                       certs.toArray(new Certificate[0]));
-            } else {
-               throw new AuthorizationException();
-            }
-         }
-         return keyStore;
-      } catch (NoSuchAlgorithmException e) {
-         throw propagate(e);
-      } catch (KeyStoreException e) {
-         throw propagate(e);
-      } catch (CertificateException e) {
-         throw propagate(e);
-      } catch (FileNotFoundException e) {
-         throw propagate(e);
-      } catch (IOException e) {
-         throw propagate(e);
-      } catch (InvalidKeySpecException e) {
-         throw propagate(e);
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java b/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java
index 59695d3..7aeee18 100644
--- a/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java
+++ b/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java
@@ -18,60 +18,146 @@ package org.jclouds.docker.suppliers;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Throwables.propagate;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.Socket;
 import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
+import java.security.KeyPair;
 import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
 import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
+import java.security.Security;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509ExtendedKeyManager;
 
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 import org.jclouds.domain.Credentials;
 import org.jclouds.http.HttpUtils;
 import org.jclouds.http.config.SSLModule.TrustAllCerts;
 import org.jclouds.location.Provider;
 
+import com.google.common.base.Charsets;
 import com.google.common.base.Supplier;
+import com.google.common.io.Files;
 
 @Singleton
 public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
-   private final Supplier<KeyStore> keyStore;
    private final TrustManager[] trustManager;
    private final Supplier<Credentials> creds;
 
    @Inject
-   SSLContextWithKeysSupplier(Supplier<KeyStore> keyStore, @Provider Supplier<Credentials> creds, HttpUtils utils,
-         TrustAllCerts trustAllCerts) {
-      this.keyStore = keyStore;
-      this.trustManager = utils.trustAllCerts() ? new TrustManager[] { trustAllCerts } : null;
+   SSLContextWithKeysSupplier(@Provider Supplier<Credentials> creds, HttpUtils utils, TrustAllCerts trustAllCerts) {
+      this.trustManager = utils.trustAllCerts() ? new TrustManager[]{trustAllCerts} : null;
       this.creds = creds;
    }
 
    @Override
    public SSLContext get() {
       Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
-      String keyStorePassword = checkNotNull(currentCreds.credential,
-            "credential supplier returned null credential (should be keyStorePassword)");
-      KeyManagerFactory kmf;
       try {
-         kmf = KeyManagerFactory.getInstance("SunX509");
-         kmf.init(keyStore.get(), keyStorePassword.toCharArray());
-         SSLContext sc = SSLContext.getInstance("TLS");
-         sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
-         return sc;
+         SSLContext sslContext = SSLContext.getInstance("TLS");
+         X509Certificate certificate = getCertificate(loadFile(currentCreds.identity));
+         PrivateKey privateKey = getKey(loadFile(currentCreds.credential));
+         sslContext.init(new KeyManager[]{new InMemoryKeyManager(certificate, privateKey)}, trustManager, new SecureRandom());
+         return sslContext;
       } catch (NoSuchAlgorithmException e) {
          throw propagate(e);
-      } catch (UnrecoverableKeyException e) {
+      } catch (KeyManagementException e) {
          throw propagate(e);
-      } catch (KeyStoreException e) {
+      } catch (CertificateException e) {
          throw propagate(e);
-      } catch (KeyManagementException e) {
+      } catch (IOException e) {
          throw propagate(e);
       }
    }
+
+   private static X509Certificate getCertificate(String certificate) {
+      try {
+         return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(
+                 new ByteArrayInputStream(certificate.getBytes(Charsets.UTF_8)));
+      } catch (CertificateException ex) {
+         throw new RuntimeException("Invalid certificate", ex);
+      }
+   }
+
+   private static PrivateKey getKey(String privateKey) {
+
+      try {
+         PEMParser pemParser = new PEMParser(new StringReader(privateKey));
+         Object object = pemParser.readObject();
+         if (Security.getProvider("BC") == null) {
+            Security.addProvider(new BouncyCastleProvider());
+         }
+         JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
+         KeyPair keyPair = converter.getKeyPair((PEMKeyPair) object);
+         return keyPair.getPrivate();
+      } catch (IOException ex) {
+         throw new RuntimeException("Invalid private key", ex);
+      }
+   }
+
+   private static String loadFile(final String filePath) throws IOException {
+      return Files.toString(new File(filePath), Charsets.UTF_8);
+   }
+
+   private static class InMemoryKeyManager extends X509ExtendedKeyManager {
+      private static final String DEFAULT_ALIAS = "docker";
+
+      private final X509Certificate certificate;
+
+      private final PrivateKey privateKey;
+
+      public InMemoryKeyManager(final X509Certificate certificate, final PrivateKey privateKey)
+              throws IOException, CertificateException {
+         this.certificate = certificate;
+         this.privateKey = privateKey;
+      }
+
+      @Override
+      public String chooseClientAlias(final String[] keyType, final Principal[] issuers,
+                                      final Socket socket) {
+         return DEFAULT_ALIAS;
+      }
+
+      @Override
+      public String chooseServerAlias(final String keyType, final Principal[] issuers,
+                                      final Socket socket) {
+         return DEFAULT_ALIAS;
+      }
+
+      @Override
+      public X509Certificate[] getCertificateChain(final String alias) {
+         return new X509Certificate[]{certificate};
+      }
+
+      @Override
+      public String[] getClientAliases(final String keyType, final Principal[] issuers) {
+         return new String[]{DEFAULT_ALIAS};
+      }
+
+      @Override
+      public PrivateKey getPrivateKey(final String alias) {
+         return privateKey;
+      }
+
+      @Override
+      public String[] getServerAliases(final String keyType, final Principal[] issuers) {
+         return new String[]{DEFAULT_ALIAS};
+      }
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java b/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
index 9aca266..447c9e4 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
@@ -29,7 +29,6 @@ import org.jboss.shrinkwrap.api.GenericArchive;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
 import org.jboss.shrinkwrap.api.exporter.TarExporter;
-import org.jclouds.Constants;
 import org.jclouds.apis.BaseApiLiveTest;
 import org.jclouds.compute.config.ComputeServiceProperties;
 import org.jclouds.docker.DockerApi;
@@ -57,8 +56,7 @@ public class BaseDockerApiLiveTest extends BaseApiLiveTest<DockerApi> {
    @Override
    protected Properties setupProperties() {
       Properties overrides = super.setupProperties();
-      overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "15");
-      overrides.setProperty("jclouds.ssh.retry-auth", "true");
+      overrides.setProperty("jclouds.trust-all-certs", "false");
       overrides.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
       return overrides;
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java b/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
index c3da551..9aae9bf 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
@@ -116,10 +116,4 @@ public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
       return ImmutableSet.<Module>of(getLoggingModule(), new SshjSshClientModule());
    }
 
-   @Override
-   protected Properties setupProperties() {
-      Properties properties = super.setupProperties();
-      properties.setProperty("jclouds.ssh.max-retries", "10");
-      return properties;
-   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java b/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
index 94ee205..850863c 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadataTest.java
@@ -34,6 +34,7 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.docker.domain.Config;
 import org.jclouds.docker.domain.Container;
 import org.jclouds.docker.domain.HostConfig;
@@ -97,12 +98,13 @@ public class ContainerToNodeMetadataTest {
             0, // exitCode
             "2014-03-24T20:28:37.537659054Z", // startedAt
             "0001-01-01T00:00:00Z", // finishedAt
-            false // ghost
+            false, // paused
+            false  // restarting
       );
       container = Container.builder()
               .id("6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9")
               .name("/hopeful_mclean")
-              .created("2014-03-22T07:16:45.784120972Z")
+              .created(new SimpleDateFormatDateService().iso8601DateParse("2014-03-22T07:16:45.784120972Z"))
               .path("/usr/sbin/sshd")
               .args(Arrays.asList("-D"))
               .config(containerConfig)

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/compute/functions/ImageToImageTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/functions/ImageToImageTest.java b/docker/src/test/java/org/jclouds/docker/compute/functions/ImageToImageTest.java
index 76d82ee..db02e3d 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/functions/ImageToImageTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/functions/ImageToImageTest.java
@@ -21,8 +21,11 @@ import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.testng.Assert.assertEquals;
 
+import java.util.Date;
+
 import org.easymock.EasyMock;
 import org.jclouds.compute.domain.Image;
+import org.jclouds.docker.domain.Config;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -41,16 +44,24 @@ public class ImageToImageTest {
    @BeforeMethod
    public void setup() {
       image = org.jclouds.docker.domain.Image.create(
-            "id", // id
-            "parent", // parent
-            "created", // created
-            null, // container
-            null, // dockerVersion
-            "x86_64", // architecture
-            null, // os
-            0l, // size
-            0l, // virtualSize
-            ImmutableList.of("repoTag1:version") // repoTags
+              "id", // id
+              "author",
+              "comment",
+              Config.builder()
+                      .image("imageId")
+                      .build(),
+              Config.builder()
+                      .image("imageId")
+                      .build(),
+              "parent", // parent
+              new Date(), // created
+              "containerId", // container
+              "1.3.1", // dockerVersion
+              "x86_64", // architecture
+              "os", // os
+              0l, // size
+              0l, // virtualSize
+              ImmutableList.of("repoTag1:version") // repoTags
       );
       function = new ImageToImage();
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java b/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java
index 44edc57..684f5de 100644
--- a/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java
@@ -16,8 +16,11 @@
  */
 package org.jclouds.docker.features;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
 import java.io.IOException;
@@ -29,8 +32,11 @@ import org.jclouds.docker.domain.Config;
 import org.jclouds.docker.domain.Container;
 import org.jclouds.docker.domain.ContainerSummary;
 import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.domain.Resource;
+import org.jclouds.docker.options.AttachOptions;
 import org.jclouds.docker.options.CreateImageOptions;
 import org.jclouds.docker.options.ListContainerOptions;
+import org.jclouds.docker.options.RemoveContainerOptions;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -57,6 +63,11 @@ public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
 
    @AfterClass
    protected void tearDown() {
+      if (container != null) {
+         if (api.getContainerApi().inspectContainer(container.id()) != null) {
+            api.getContainerApi().removeContainer(container.id(), RemoveContainerOptions.Builder.force(true));
+         }
+      }
       if (image != null) {
          api.getImageApi().deleteImage(BUSYBOX_IMAGE_TAG);
       }
@@ -64,7 +75,7 @@ public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
 
    public void testCreateContainer() throws IOException, InterruptedException {
       Config containerConfig = Config.builder().image(image.id())
-              .cmd(ImmutableList.of("/bin/sh", "-c", "while true; do echo hello world; sleep 1; done"))
+              .cmd(ImmutableList.of("/bin/sh", "-c", "touch hello; while true; do echo hello world; sleep 1; done"))
               .build();
       container = api().createContainer("testCreateContainer", containerConfig);
       assertNotNull(container);
@@ -78,11 +89,54 @@ public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
    }
 
    @Test(dependsOnMethods = "testStartContainer")
+   public void testAttachContainer() {
+      InputStream attachStream = api().attach(container.id(), AttachOptions.Builder.logs(true).stream(false).stdout(true));
+      String stream = consumeStream(attachStream);
+      assertThat(stream.trim()).contains("hello world");
+   }
+
+   @Test(dependsOnMethods = "testAttachContainer")
+   public void testCopyFileFromContainer() {
+      InputStream tarredStream = api().copy(container.id(), Resource.create("hello"));
+      assertNotNull(consumeStream(tarredStream));
+   }
+
+   @Test(dependsOnMethods = "testCopyFileFromContainer")
+   public void testPauseContainer() {
+      api().pause(container.id());
+      assertTrue(api().inspectContainer(container.id()).state().paused());
+   }
+
+   @Test(dependsOnMethods = "testPauseContainer")
+   public void testUnpauseContainer() {
+      api().unpause(container.id());
+      assertFalse(api().inspectContainer(container.id()).state().paused());
+   }
+
+   @Test(dependsOnMethods = "testUnpauseContainer")
    public void testStopContainer() {
       api().stopContainer(container.id());
       assertFalse(api().inspectContainer(container.id()).state().running());
    }
 
+   @Test(dependsOnMethods = "testStopContainer")
+   public void testRestartContainer() {
+      api().restart(container.id());
+      assertTrue(api().inspectContainer(container.id()).state().running());
+   }
+
+   @Test(dependsOnMethods = "testRestartContainer")
+   public void testWaitContainer() {
+      api().stopContainer(container.id(), 1);
+      assertEquals(api().wait(container.id()).statusCode(), -1);
+   }
+
+   @Test(dependsOnMethods = "testWaitContainer")
+   public void testRemoveContainer() {
+      api().removeContainer(container.id());
+      assertNull(api().inspectContainer(container.id()));
+   }
+
    @Test
    public void testListContainers() {
       List<ContainerSummary> containerSummaries = api().listContainers(ListContainerOptions.Builder.all(true));
@@ -93,12 +147,6 @@ public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
       }
    }
 
-   @Test(dependsOnMethods = "testStopContainer", expectedExceptions = NullPointerException.class)
-   public void testRemoveContainer() {
-      api().removeContainer(container.id());
-      assertFalse(api().inspectContainer(container.id()).state().running());
-   }
-
    private ContainerApi api() {
       return api.getContainerApi();
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/features/ContainerApiMockTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/features/ContainerApiMockTest.java b/docker/src/test/java/org/jclouds/docker/features/ContainerApiMockTest.java
index 4bbff66..ab3657b 100644
--- a/docker/src/test/java/org/jclouds/docker/features/ContainerApiMockTest.java
+++ b/docker/src/test/java/org/jclouds/docker/features/ContainerApiMockTest.java
@@ -16,23 +16,22 @@
  */
 package org.jclouds.docker.features;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-import java.util.List;
 
 import org.jclouds.docker.DockerApi;
+import org.jclouds.docker.config.DockerParserModule;
 import org.jclouds.docker.domain.Config;
 import org.jclouds.docker.domain.Container;
-import org.jclouds.docker.domain.ContainerSummary;
+import org.jclouds.docker.domain.Resource;
 import org.jclouds.docker.internal.BaseDockerMockTest;
 import org.jclouds.docker.options.ListContainerOptions;
-import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.docker.parse.ContainerParseTest;
+import org.jclouds.docker.parse.ContainersParseTest;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMultimap;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 
@@ -43,96 +42,56 @@ import com.squareup.okhttp.mockwebserver.MockWebServer;
 public class ContainerApiMockTest extends BaseDockerMockTest {
 
    public void testListContainers() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
-
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
-
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/containers.json")));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         List<ContainerSummary> containerSummaries = api.listContainers();
-         assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
-         assertEquals(containerSummaries.size(), 1);
+         assertEquals(api.listContainers(), new ContainersParseTest().expected());
+         assertSent(server, "GET", "/containers/json");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testListNonexistentContainers() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(404));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         List<ContainerSummary> containerSummaries = api.listContainers();
-         assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
-         assertTrue(containerSummaries.isEmpty());
+         assertEquals(api.listContainers(), ImmutableList.of());
+         assertSent(server, "GET", "/containers/json");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-
    @Test(timeOut = 10000l)
    public void testListAllContainers() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/containers.json")));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         List<ContainerSummary> containerSummaries = api.listContainers(ListContainerOptions.Builder.all(true));
-         assertRequestHasParameters(server.takeRequest(), "/containers/json", ImmutableMultimap.of("all", "true"));
-         assertEquals(containerSummaries.size(), 1);
+         assertEquals(api.listContainers(ListContainerOptions.Builder.all(true)), new ContainersParseTest().expected());
+         assertSent(server, "GET", "/containers/json?all=true");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testGetContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/container.json")));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/container.json")));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getContainerApi();
       String containerId = "b03d4cd15b76f8876110615cdeed15eadf77c9beb408d62f1687dcc69192cd6d";
       try {
-         Container container = api.inspectContainer(containerId);
-         assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
-         assertNotNull(container);
-         assertNotNull(container.id(), containerId);
-         assertNotNull(container.config());
-         assertNotNull(container.hostConfig());
-         assertTrue(container.name().contains("/weave"));
-         assertEquals(container.state().running(), true);
+         assertEquals(api.inspectContainer(containerId), new ContainerParseTest().expected());
+         assertSent(server, "GET", "/containers/" + containerId + "/json");
       } finally {
-         dockerApi.close();
-         server.shutdown();
-      }
-   }
-
-   public void testGetNonExistingContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
-      String containerId = "notExisting";
-      try {
-         Container container = api.inspectContainer(containerId);
-         assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
-      } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testCreateContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/container-creation.json")));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
-      Config containerConfig = Config.builder().cmd(ImmutableList.of("date"))
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/container-creation.json")));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      Config containerConfig = Config.builder()
+              .cmd(ImmutableList.of("date"))
               .attachStdin(false)
               .attachStderr(true)
               .attachStdout(true)
@@ -141,106 +100,135 @@ public class ContainerApiMockTest extends BaseDockerMockTest {
               .build();
       try {
          Container container = api.createContainer("test", containerConfig);
-         assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/create?name=test");
+         assertSent(server, "POST", "/containers/create?name=test");
          assertNotNull(container);
-         assertEquals(container.id(), "c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2");
+         assertThat(container.id()).isEqualTo("c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testRemoveContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(204));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       String containerId = "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9";
 
       try {
          api.removeContainer(containerId);
-         assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/containers/" + containerId);
+         assertSent(server, "DELETE", "/containers/" + containerId);
+
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testRemoveNonExistingContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
-      String containerId = "nonExisting";
+   public void testStartContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         api.removeContainer(containerId);
-         fail("Remove container must fail on 404");
-      } catch (ResourceNotFoundException ex) {
-         // Expected exception
+         api.startContainer("1");
+         assertSent(server, "POST", "/containers/1/start");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testStartContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(200));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+   public void testStopContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         api.startContainer("1");
-         assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/start");
+         api.stopContainer("1");
+         assertSent(server, "POST", "/containers/1/stop");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testStartNonExistingContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+
+   public void testCommitContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(201));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         try {
-            api.startContainer("1");
-            fail("Start container must fail on 404");
-         } catch (ResourceNotFoundException ex) {
-            // Expected exception
-         }
+         api.commit();
+         assertSent(server, "POST", "/commit");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testStopContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(200));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+   public void testPauseContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         api.stopContainer("1");
-         assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/stop");
+         api.pause("1");
+         assertSent(server, "POST", "/containers/1/pause");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testStopNonExistingContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ContainerApi api = dockerApi.getContainerApi();
+   public void testUnpauseContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
       try {
-         api.stopContainer("1");
-         fail("Stop container must fail on 404");
-      } catch (ResourceNotFoundException ex) {
-         // Expected exception
+         api.unpause("1");
+         assertSent(server, "POST", "/containers/1/unpause");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testAttachContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      try {
+         api.attach("1");
+         assertSent(server, "POST", "/containers/1/attach");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testWaitContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      try {
+         api.wait("1");
+         assertSent(server, "POST", "/containers/1/wait");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testRestartContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      try {
+         api.restart("1");
+         assertSent(server, "POST", "/containers/1/restart");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testKillContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      try {
+         api.kill("1");
+         assertSent(server, "POST", "/containers/1/kill");
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testCopyFileFromContainer() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
+      try {
+         api.copy("1", Resource.create("test"));
+         assertSent(server, "POST", "/containers/1/copy");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/features/ImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/features/ImageApiMockTest.java b/docker/src/test/java/org/jclouds/docker/features/ImageApiMockTest.java
index 7ad6414..5349c39 100644
--- a/docker/src/test/java/org/jclouds/docker/features/ImageApiMockTest.java
+++ b/docker/src/test/java/org/jclouds/docker/features/ImageApiMockTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.docker.features;
 
-import static org.testng.Assert.fail;
+import static org.testng.Assert.assertEquals;
 
 import org.jclouds.docker.DockerApi;
+import org.jclouds.docker.config.DockerParserModule;
 import org.jclouds.docker.internal.BaseDockerMockTest;
 import org.jclouds.docker.options.CreateImageOptions;
-import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.docker.parse.ImageParseTest;
+import org.jclouds.docker.parse.ImagesParseTest;
 import org.testng.annotations.Test;
 
-import com.google.common.collect.ImmutableMultimap;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 
@@ -35,61 +36,47 @@ import com.squareup.okhttp.mockwebserver.MockWebServer;
 public class ImageApiMockTest extends BaseDockerMockTest {
 
    public void testCreateImage() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(200));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ImageApi api = dockerApi.getImageApi();
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
       try {
          api.createImage(CreateImageOptions.Builder.fromImage("base"));
-         assertRequestHasParameters(server.takeRequest(), "POST", "/images/create", ImmutableMultimap.of("fromImage", "base"));
+         assertSent(server, "POST", "/images/create?fromImage=base");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testCreateImageFailure() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ImageApi api = dockerApi.getImageApi();
+   public void testGetImage() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/image.json")));
+      ImageApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getImageApi();
       try {
-         api.createImage(CreateImageOptions.Builder.fromImage("base"));
-         fail("Create image must fail on 404");
-      } catch (ResourceNotFoundException ex) {
-         // Expected exception
+         String imageId = "cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456";
+         assertEquals(api.inspectImage(imageId), new ImageParseTest().expected());
+         assertSent(server, "GET", "/images/" + imageId + "/json");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testDeleteImage() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(204));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ImageApi api = dockerApi.getImageApi();
+   public void testListImages() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/images.json")));
+      ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
       try {
-         api.deleteImage("1");
-         assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/images/1");
+         assertEquals(api.listImages(), new ImagesParseTest().expected());
+         assertSent(server, "GET", "/images/json");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
-   public void testDeleteNotExistingImage() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      ImageApi api = dockerApi.getImageApi();
+   public void testDeleteImage() throws Exception {
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
+      ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
       try {
          api.deleteImage("1");
-         fail("Delete image must fail on 404");
-      } catch (ResourceNotFoundException ex) {
-         // Expected exception
+         assertSent(server, "DELETE", "/images/1");
+
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/features/MiscApiLiveTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/features/MiscApiLiveTest.java b/docker/src/test/java/org/jclouds/docker/features/MiscApiLiveTest.java
index b14a108..bfe1b40 100644
--- a/docker/src/test/java/org/jclouds/docker/features/MiscApiLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/features/MiscApiLiveTest.java
@@ -18,7 +18,6 @@ package org.jclouds.docker.features;
 
 import org.jclouds.docker.compute.BaseDockerApiLiveTest;
 import org.jclouds.docker.options.BuildOptions;
-import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.assertEquals;
@@ -34,10 +33,10 @@ import com.google.common.collect.Iterables;
 public class MiscApiLiveTest extends BaseDockerApiLiveTest {
 
    private static final String API_VERSION = "1.15";
-   private static final String VERSION = "1.3.0";
-   private static final String GIT_COMMIT = "c78088f";
+   private static final String VERSION = "1.3.2";
+   private static final String GIT_COMMIT = "39fa2fa";
    private static final String GO_VERSION = "go1.3.3";
-   private static final String KERNEL_VERSION = "3.16.4-tinycore64";
+   private static final String KERNEL_VERSION = "3.16.7-tinycore64";
    private static final String ARCH = "amd64";
    private static final String OS = "linux";
 
@@ -71,13 +70,6 @@ public class MiscApiLiveTest extends BaseDockerApiLiveTest {
       assertNotNull(imageId);
    }
 
-   @AfterClass
-   protected void tearDown() {
-      if (imageId != null) {
-         consumeStream(api.getImageApi().deleteImage(imageId));
-      }
-   }
-
    private MiscApi api() {
       return api.getMiscApi();
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/features/MiscApiMockTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/features/MiscApiMockTest.java b/docker/src/test/java/org/jclouds/docker/features/MiscApiMockTest.java
index e7b1e5b..630d7af 100644
--- a/docker/src/test/java/org/jclouds/docker/features/MiscApiMockTest.java
+++ b/docker/src/test/java/org/jclouds/docker/features/MiscApiMockTest.java
@@ -19,19 +19,15 @@ package org.jclouds.docker.features;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 import org.jclouds.docker.DockerApi;
-import org.jclouds.docker.domain.Info;
-import org.jclouds.docker.domain.Version;
 import org.jclouds.docker.internal.BaseDockerMockTest;
-import org.jclouds.docker.options.BuildOptions;
+import org.jclouds.docker.parse.InfoParseTest;
+import org.jclouds.docker.parse.VersionParseTest;
 import org.jclouds.io.Payload;
 import org.jclouds.io.Payloads;
-import org.jclouds.rest.ResourceNotFoundException;
 import org.testng.annotations.Test;
 
 import static org.jclouds.docker.compute.BaseDockerApiLiveTest.tarredDockerfile;
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
 import java.io.File;
 import java.io.FileInputStream;
 
@@ -41,117 +37,50 @@ import java.io.FileInputStream;
 @Test(groups = "unit", testName = "MiscApiMockTest")
 public class MiscApiMockTest extends BaseDockerMockTest {
 
-   private static final String API_VERSION = "1.15";
-   private static final String VERSION = "1.3.0";
-   private static final String GIT_COMMIT = "c78088f";
-   private static final String GO_VERSION = "go1.3.3";
-   private static final String KERNEL_VERSION = "3.16.4-tinycore64";
-   private static final String ARCH = "amd64";
-   private static final String OS = "linux";
-
    public void testGetVersion() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/version.json")));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      MiscApi api = dockerApi.getMiscApi();
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/version.json")));
+      MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
       try {
-         Version version = api.getVersion();
-         assertRequestHasCommonFields(server.takeRequest(), "/version");
-         assertNotNull(version);
-         assertEquals(version.version(), VERSION);
-         assertEquals(version.gitCommit(), GIT_COMMIT);
-         assertEquals(version.apiVersion(), API_VERSION);
-         assertEquals(version.goVersion(), GO_VERSION);
-         assertEquals(version.kernelVersion(), KERNEL_VERSION);
-         assertEquals(version.arch(), ARCH);
-         assertEquals(version.os(), OS);
+         assertEquals(api.getVersion(), new VersionParseTest().expected());
+         assertSent(server, "GET", "/version");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testGetInfo() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setBody(payloadFromResource("/info.json")));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      MiscApi api = dockerApi.getMiscApi();
-
+      MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/info.json")));
+      MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
       try {
-         Info info = api.getInfo();
-         assertRequestHasCommonFields(server.takeRequest(), "/info");
-         assertNotNull(info);
-         assertNotNull(info.containers());
-         assertNotNull(info.debug());
-         assertNotNull(info.driver());
-         assertNotNull(info.executionDriver());
-         assertNotNull(info.images());
-         assertNotNull(info.indexServerAddress());
-         assertNotNull(info.initPath());
-         assertNotNull(info.iPv4Forwarding());
-         assertNotNull(info.kernelVersion());
-         assertNotNull(info.memoryLimit());
-         assertNotNull(info.nEventsListener());
-         assertNotNull(info.nFd());
-         assertNotNull(info.nGoroutines());
-         assertNotNull(info.swapLimit());
+         assertEquals(api.getInfo(), new InfoParseTest().expected());
+         assertSent(server, "GET", "/info");
       } finally {
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testBuildContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(200));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      MiscApi api = dockerApi.getMiscApi();
-      File dockerFile = File.createTempFile("docker", "tmp");
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
       try {
-         api.build(tarredDockerfile(), BuildOptions.NONE);
-         assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
+         api.build(tarredDockerfile());
+         assertSent(server, "POST", "/build");
       } finally {
-         dockerFile.delete();
-         dockerApi.close();
          server.shutdown();
       }
    }
 
    public void testBuildContainerUsingPayload() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(200));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      MiscApi api = dockerApi.getMiscApi();
+      MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
+      MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
       File file = File.createTempFile("docker", "tmp");
       FileInputStream data = new FileInputStream(file);
       Payload payload = Payloads.newInputStreamPayload(data);
       payload.getContentMetadata().setContentLength(file.length());
-
-      try {
-         api.build(payload, BuildOptions.NONE);
-         assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
-      } finally {
-         dockerApi.close();
-         server.shutdown();
-      }
-   }
-
-   public void testBuildNonexistentContainer() throws Exception {
-      MockWebServer server = mockWebServer();
-      server.enqueue(new MockResponse().setResponseCode(404));
-      DockerApi dockerApi = api(server.getUrl("/"));
-      MiscApi api = dockerApi.getMiscApi();
-      File dockerFile = File.createTempFile("docker", "tmp");
       try {
-         try {
-            api.build(tarredDockerfile(), BuildOptions.NONE);
-            fail("Build container must fail on 404");
-         } catch (ResourceNotFoundException ex) {
-            // Expected exception
-         }
+         api.build(payload);
+         assertSent(server, "POST", "/build");
       } finally {
-         dockerFile.delete();
-         dockerApi.close();
          server.shutdown();
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/internal/BaseDockerMockTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/internal/BaseDockerMockTest.java b/docker/src/test/java/org/jclouds/docker/internal/BaseDockerMockTest.java
index efdc9b5..994519e 100644
--- a/docker/src/test/java/org/jclouds/docker/internal/BaseDockerMockTest.java
+++ b/docker/src/test/java/org/jclouds/docker/internal/BaseDockerMockTest.java
@@ -16,27 +16,19 @@
  */
 package org.jclouds.docker.internal;
 
-import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
-import static org.jclouds.http.utils.Queries.encodeQueryLine;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.jclouds.util.Strings2.toStringAndClose;
-import static org.testng.Assert.assertEquals;
 import java.io.IOException;
-import java.net.URL;
 import java.util.Properties;
-import java.util.Set;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 
-import org.jclouds.ContextBuilder;
-import org.jclouds.concurrent.config.ExecutorServiceModule;
-import org.jclouds.docker.DockerApi;
+import org.jclouds.http.BaseMockWebServerTest;
+import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
 import com.google.inject.Module;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 import com.squareup.okhttp.mockwebserver.RecordedRequest;
@@ -44,33 +36,18 @@ import com.squareup.okhttp.mockwebserver.RecordedRequest;
 /**
  * Base class for all Docker mock tests.
  */
-public class BaseDockerMockTest {
-   private final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(),
-         sameThreadExecutor()));
+public class BaseDockerMockTest extends BaseMockWebServerTest {
 
-   protected String provider;
+   protected static final String API_VERSION = "1.15";
 
-   public BaseDockerMockTest() {
-      provider = "docker";
+   @Override
+   protected void addOverrideProperties(Properties properties) {
+      properties.setProperty("jclouds.api-version", API_VERSION);
    }
 
-   public DockerApi api(URL url) {
-      return ContextBuilder.newBuilder(provider)
-            .credentials("clientid", "apikey")
-            .endpoint(url.toString())
-            .modules(modules)
-            .overrides(setupProperties())
-            .buildApi(DockerApi.class);
-   }
-
-   protected Properties setupProperties() {
-      return new Properties();
-   }
-
-   public static MockWebServer mockWebServer() throws IOException {
-      MockWebServer server = new MockWebServer();
-      server.play();
-      return server;
+   @Override
+   protected Module createConnectionModule() {
+      return new OkHttpCommandExecutorServiceModule();
    }
 
    public byte[] payloadFromResource(String resource) {
@@ -81,38 +58,12 @@ public class BaseDockerMockTest {
       }
    }
 
-   protected static void assertRequestHasCommonFields(final RecordedRequest request, final String path)
-           throws InterruptedException {
-      assertRequestHasParameters(request, "GET", path, ImmutableMultimap.<String, String> of());
-   }
-
-   protected static void assertRequestHasCommonFields(final RecordedRequest request,
-                                                      final String verb, final String path)
-         throws InterruptedException {
-      assertRequestHasParameters(request, verb, path, ImmutableMultimap.<String, String> of());
-   }
-
-   protected static void assertRequestHasParameters(final RecordedRequest request, final String path,
-                                                    Multimap<String, String> parameters) throws InterruptedException {
-      assertRequestHasParameters(request, "GET", path, parameters);
-   }
-
-   protected static void assertRequestHasParameters(final RecordedRequest request, String verb, final String path,
-                                                    Multimap<String, String> parameters) throws InterruptedException {
-      String queryParameters = "";
-      if (!parameters.isEmpty()) {
-         Multimap<String, String> allparams = ImmutableMultimap.<String, String>builder()
-                 .putAll(parameters)
-                 .build();
-
-         assertRequestHasAcceptHeader(request);
-         queryParameters = "?" + encodeQueryLine(allparams);
-      }
-      assertEquals(request.getRequestLine(), verb + " " + path + queryParameters + " HTTP/1.1");
-   }
-
-   protected static void assertRequestHasAcceptHeader(final RecordedRequest request) throws InterruptedException {
-      assertEquals(request.getHeader(HttpHeaders.ACCEPT), MediaType.APPLICATION_JSON);
+   protected RecordedRequest assertSent(MockWebServer server, String method, String path) throws InterruptedException {
+      RecordedRequest request = server.takeRequest();
+      assertThat(request.getMethod()).isEqualTo(method);
+      assertThat(request.getPath()).isEqualTo("/v" + API_VERSION + path);
+      assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON);
+      return request;
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/internal/BaseDockerParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/internal/BaseDockerParseTest.java b/docker/src/test/java/org/jclouds/docker/internal/BaseDockerParseTest.java
new file mode 100644
index 0000000..5227ff8
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/internal/BaseDockerParseTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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 org.jclouds.docker.internal;
+
+import org.jclouds.docker.config.DockerParserModule;
+import org.jclouds.json.BaseItemParserTest;
+import org.jclouds.json.config.GsonModule;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+public abstract class BaseDockerParseTest<T>  extends BaseItemParserTest<T> {
+
+   @Override
+   protected Injector injector() {
+      return Guice.createInjector(new GsonModule(), new DockerParserModule());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/ContainerParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/ContainerParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/ContainerParseTest.java
new file mode 100644
index 0000000..dc5c791
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/ContainerParseTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.docker.domain.Config;
+import org.jclouds.docker.domain.Container;
+import org.jclouds.docker.domain.HostConfig;
+import org.jclouds.docker.domain.NetworkSettings;
+import org.jclouds.docker.domain.State;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@Test(groups = "unit")
+public class ContainerParseTest extends BaseDockerParseTest<Container> {
+
+   @Override
+   public String resource() {
+      return "/container.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Container expected() {
+      return Container.builder()
+              .id("6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524")
+              .created(new SimpleDateFormatDateService().iso8601DateParse("2014-10-31T17:00:21.544197943Z"))
+              .path("/home/weave/weaver")
+              .name("/weave")
+              .args(ImmutableList.of("-iface", "ethwe", "-wait", "5", "-name", "7a:63:a2:39:7b:0f"))
+              .config(Config.builder()
+                      .hostname("6c9932f478bd")
+                      .env(ImmutableList.of("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"))
+                      .image("57e570db16baba1e8c0d6f3c15868ddb400f64ff76ec948e65c3ca3f15fb3587")
+                      .domainname("")
+                      .user("")
+                      .cmd(ImmutableList.of("-name", "7a:63:a2:39:7b:0f"))
+                      .entrypoint(ImmutableList.of("/home/weave/weaver", "-iface", "ethwe", "-wait", "5"))
+                      .image("zettio/weave")
+                      .workingDir("/home/weave")
+                      .exposedPorts(ImmutableMap.of("6783/tcp", ImmutableMap.of(), "6783/udp", ImmutableMap.of()))
+                      .build())
+              .state(State.create(3939, true, 0, "2014-10-31T17:00:21.802008706Z", "0001-01-01T00:00:00Z", false, false))
+              .image("57e570db16baba1e8c0d6f3c15868ddb400f64ff76ec948e65c3ca3f15fb3587")
+              .networkSettings(NetworkSettings.builder()
+                      .ipAddress("172.17.0.7")
+                      .ipPrefixLen(16)
+                      .gateway("172.17.42.1")
+                      .bridge("docker0")
+                      .ports(ImmutableMap.<String, List<Map<String, String>>>of(
+                                      "6783/tcp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "0.0.0.0", "HostPort", "6783")),
+                                      "6783/udp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "0.0.0.0", "HostPort", "6783")))
+                      )
+                      .build())
+              .resolvConfPath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/resolv.conf")
+              .hostConfig(HostConfig.builder()
+                      .containerIDFile("")
+                      .portBindings(ImmutableMap.<String, List<Map<String, String>>>of(
+                                      "6783/tcp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "", "HostPort", "6783")),
+                                      "6783/udp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "", "HostPort", "6783")))
+                      )
+                      .privileged(true)
+                      .build())
+              .driver("aufs")
+              .execDriver("native-0.2")
+              .hostnamePath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hostname")
+              .hostsPath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hosts")
+              .mountLabel("")
+              .processLabel("")
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/ContainersParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/ContainersParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/ContainersParseTest.java
new file mode 100644
index 0000000..bb3bd62
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/ContainersParseTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.docker.domain.ContainerSummary;
+import org.jclouds.docker.domain.Port;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit")
+public class ContainersParseTest extends BaseDockerParseTest<List<ContainerSummary>> {
+
+   @Override
+   public String resource() {
+      return "/containers.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public List<ContainerSummary> expected() {
+      return ImmutableList.of(
+              ContainerSummary.create("6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9",
+                      ImmutableList.of("/hopeful_mclean"),
+                      "1395472605",
+                      "jclouds/ubuntu:latest",
+                      "/usr/sbin/sshd -D",
+                      ImmutableList.of(Port.create("0.0.0.0", 22, 49231, "tcp")),
+                      "Up 55 seconds")
+      );
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/ImageParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/ImageParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/ImageParseTest.java
new file mode 100644
index 0000000..038be86
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/ImageParseTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.docker.domain.Config;
+import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+import com.beust.jcommander.internal.Maps;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@Test(groups = "unit")
+public class ImageParseTest extends BaseDockerParseTest<Image> {
+
+   @Override
+   public String resource() {
+      return "/image.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Image expected() {
+      return Image.create("cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456",
+              "author",
+              "comment",
+              Config.builder().cmd(ImmutableList.of("/bin/sh", "-c", "echo hello world"))
+                      .env(ImmutableList.of(
+                                      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+                                      "HOME=/root",
+                                      "JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64"
+                              )
+                      )
+                      .exposedPorts(ImmutableMap.of("8081/tcp", Maps.newHashMap()))
+                      .hostname("f22711318734")
+                      .domainname("")
+                      .user("user")
+                      .image("05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba")
+                      .workingDir("/home/user")
+                      .build(),
+              Config.builder().cmd(ImmutableList.of("/bin/sh", "-c", "echo hello world"))
+                      .env(ImmutableList.of(
+                                      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+                                      "HOME=/root",
+                                      "JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64")
+                      )
+                      .exposedPorts(ImmutableMap.of("8081/tcp", Maps.newHashMap()))
+                      .hostname("f22711318734")
+                      .domainname("")
+                      .user("user")
+                      .image("05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba")
+                      .workingDir("/home/user")
+                      .build(),
+              "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+              new SimpleDateFormatDateService().iso8601DateParse("2014-11-24T11:09:20.310023104Z"),
+              "0d14967353dbbd2ee78abe209f026f71654da49692fa2b044296ec3c810027b3",
+              "1.3.1",
+              "amd64",
+              "linux",
+              0,
+              808709069,
+              null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/ImagesParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/ImagesParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/ImagesParseTest.java
new file mode 100644
index 0000000..d2ef5b6
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/ImagesParseTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.docker.domain.ImageSummary;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit")
+public class ImagesParseTest extends BaseDockerParseTest<List<ImageSummary>> {
+
+   @Override
+   public String resource() {
+      return "/images.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public List<ImageSummary> expected() {
+      return ImmutableList.of(
+              ImageSummary.create("cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456",
+                      1416827360,
+                      "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+                      0,
+                      808709069,
+                      ImmutableList.of("test:latest")),
+              ImageSummary.create("e1e548b03259ae30ba12232b6c16ef5205cf71b0363848e78b0394e1ecba4f57",
+                      1416826851,
+                      "6f36bec79c7f184ceebf7000cfb7244c4bc9b397b6659ac7f420a53d114250d9",
+                      0,
+                      5609404,
+                      ImmutableList.of("<none>:<none>")),
+              ImageSummary.create("8201388d2b288539aab6aabf5d3b15ec269eba95c6baa9d6771f16540abf3a3f",
+                      1414247273,
+                      "4671e2c549c5b60063e349f520c801dc73b53d2226a5a8e5501845ebe94761ca",
+                      0,
+                      755313702,
+                      ImmutableList.of("dockerfile/java:openjdk-7-jdk")),
+              ImageSummary.create("5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5",
+                      1414108439,
+                      "22093c35d77bb609b9257ffb2640845ec05018e3d96cb939f68d0e19127f1723",
+                      0,
+                      199257566,
+                      ImmutableList.of("ubuntu:14.04"))
+      );
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/InfoParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/InfoParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/InfoParseTest.java
new file mode 100644
index 0000000..5527e28
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/InfoParseTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.docker.domain.Info;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "unit")
+public class InfoParseTest extends BaseDockerParseTest<Info> {
+
+   @Override
+   public String resource() {
+      return "/info.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Info expected() {
+      return Info.create(0,
+              1,
+              "aufs",
+              ImmutableList.<List<String>>of(
+                      ImmutableList.of("Root Dir", "/mnt/sda1/var/lib/docker/aufs"),
+                      ImmutableList.of("Dirs", "15")
+              ),
+              "native-0.2",
+              1,
+              15,
+              "https://index.docker.io/v1/",
+              "/usr/local/bin/docker",
+              "",
+              "3.16.4-tinycore64",
+              1,
+              0,
+              10,
+              11,
+              "Boot2Docker 1.3.0 (TCL 5.4); master : a083df4 - Thu Oct 16 17:05:03 UTC 2014",
+              1);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/java/org/jclouds/docker/parse/VersionParseTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/parse/VersionParseTest.java b/docker/src/test/java/org/jclouds/docker/parse/VersionParseTest.java
new file mode 100644
index 0000000..2d9781b
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/parse/VersionParseTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.jclouds.docker.parse;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.docker.domain.Version;
+import org.jclouds.docker.internal.BaseDockerParseTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit")
+public class VersionParseTest extends BaseDockerParseTest<Version> {
+
+   @Override
+   public String resource() {
+      return "/version.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Version expected() {
+      return Version.create(
+              "1.15",
+              "amd64",
+              "c78088f",
+              "go1.3.3",
+              "3.16.4-tinycore64",
+              "linux",
+              "1.3.0");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/resources/cert.pem
----------------------------------------------------------------------
diff --git a/docker/src/test/resources/cert.pem b/docker/src/test/resources/cert.pem
new file mode 100644
index 0000000..ab2c41a
--- /dev/null
+++ b/docker/src/test/resources/cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIJAL/TuOknjSR5MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQxMjEyMTYwMDEyWhcNMjQxMjA5MTYwMDEyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAuUQcWlhrMXmzLSLiHUADdF98IHKRde7I1eDT91NndOtx4pKfvVc3WPei
+REIMksrU8F1r4A086h5++xxDf27LxR4EC9ry0Q6GgJ9Un9RB9clCWRhLw8awHAS7
+HgAEN8YOSCeF3qP+78muxyMkIKQbYn3TqqOzRZcK576hX+a6URNJDhbHHAzq2fxm
+rOSRVdPXzKLl48ABfmqJ6+KiXc6e7mQSgmwBLfh51zxmJNNwZ5e+6sfZ8oz4yM4y
+Kzek53GRSFj+VFNp5nS/x2072fUak2i6DGut5LibFfh1kqskIm+Iq5WwO15RbojZ
+CR6fkktCl5QOtea5p8SETZpwWfaddQIDAQABo4GnMIGkMB0GA1UdDgQWBBQtOc1g
+1gxisDQ7VTmRYI1U9WHVMDB1BgNVHSMEbjBsgBQtOc1g1gxisDQ7VTmRYI1U9WHV
+MKFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAL/TuOknjSR5MAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABxYn5JdJYC8FUITqymJeNZ72/a2GVf8
++gGlWH+DuiyviEAGMGpv7O4GXfS/6UiUBO7zMe2z15fUvNgd5RQBh4T+l5bA9aS0
+5JhENIpEApiIcEII4ISIk6pTLmAZjWvqq2kStiiFPNvdKFclYqFuKHv847EA8kGz
+9u6MuUyFrJipWZ3g8zeYiwLWaAzvimbHomO7HU4pcvYaCSl7O5BQTToKwLfHcx5y
+UG6uRf+0auC5QbotiXpYNdXhIbSD/2xXbjxGwYy4yRWHINcbwfK8iVRhR4eSvtBC
+WvF3Vp8xLJxp6ujBd+a27AOWEiE1XM8oAoUpEzdIINY1GtUSbXzNboc=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/resources/image.json
----------------------------------------------------------------------
diff --git a/docker/src/test/resources/image.json b/docker/src/test/resources/image.json
new file mode 100644
index 0000000..8d34de7
--- /dev/null
+++ b/docker/src/test/resources/image.json
@@ -0,0 +1,83 @@
+{
+  "Architecture": "amd64",
+  "Author": "author",
+  "Comment": "comment",
+  "Config": {
+    "AttachStderr": false,
+    "AttachStdin": false,
+    "AttachStdout": false,
+    "Cmd": [
+      "/bin/sh",
+      "-c",
+      "echo hello world"
+    ],
+    "CpuShares": 0,
+    "Cpuset": "",
+    "Domainname": "",
+    "Entrypoint": null,
+    "Env": [
+      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+      "HOME=/root",
+      "JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64"
+    ],
+    "ExposedPorts": {
+      "8081/tcp": {}
+    },
+    "Hostname": "f22711318734",
+    "Image": "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+    "Memory": 0,
+    "MemorySwap": 0,
+    "NetworkDisabled": false,
+    "OnBuild": [],
+    "OpenStdin": false,
+    "PortSpecs": null,
+    "StdinOnce": false,
+    "Tty": false,
+    "User": "user",
+    "Volumes": null,
+    "WorkingDir": "/home/user"
+  },
+  "Container": "0d14967353dbbd2ee78abe209f026f71654da49692fa2b044296ec3c810027b3",
+  "ContainerConfig": {
+    "AttachStderr": false,
+    "AttachStdin": false,
+    "AttachStdout": false,
+    "Cmd": [
+      "/bin/sh",
+      "-c",
+      "echo hello world"
+    ],
+    "CpuShares": 0,
+    "Cpuset": "",
+    "Domainname": "",
+    "Entrypoint": null,
+    "Env": [
+      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+      "HOME=/root",
+      "JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64"
+    ],
+    "ExposedPorts": {
+      "8081/tcp": {}
+    },
+    "Hostname": "f22711318734",
+    "Image": "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+    "Memory": 0,
+    "MemorySwap": 0,
+    "NetworkDisabled": false,
+    "OnBuild": [],
+    "OpenStdin": false,
+    "PortSpecs": null,
+    "StdinOnce": false,
+    "Tty": false,
+    "User": "user",
+    "Volumes": null,
+    "WorkingDir": "/home/user"
+  },
+  "Created": "2014-11-24T11:09:20.310023104Z",
+  "DockerVersion": "1.3.1",
+  "Id": "cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456",
+  "Os": "linux",
+  "Parent": "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+  "Size": 0,
+  "VirtualSize": 808709069
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/74cefc97/docker/src/test/resources/images.json
----------------------------------------------------------------------
diff --git a/docker/src/test/resources/images.json b/docker/src/test/resources/images.json
new file mode 100644
index 0000000..41d4f12
--- /dev/null
+++ b/docker/src/test/resources/images.json
@@ -0,0 +1,42 @@
+[
+  {
+    "Created": 1416827360,
+    "Id": "cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456",
+    "ParentId": "05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
+    "RepoTags": [
+      "test:latest"
+    ],
+    "Size": 0,
+    "VirtualSize": 808709069
+  },
+  {
+    "Created": 1416826851,
+    "Id": "e1e548b03259ae30ba12232b6c16ef5205cf71b0363848e78b0394e1ecba4f57",
+    "ParentId": "6f36bec79c7f184ceebf7000cfb7244c4bc9b397b6659ac7f420a53d114250d9",
+    "RepoTags": [
+      "<none>:<none>"
+    ],
+    "Size": 0,
+    "VirtualSize": 5609404
+  },
+  {
+    "Created": 1414247273,
+    "Id": "8201388d2b288539aab6aabf5d3b15ec269eba95c6baa9d6771f16540abf3a3f",
+    "ParentId": "4671e2c549c5b60063e349f520c801dc73b53d2226a5a8e5501845ebe94761ca",
+    "RepoTags": [
+      "dockerfile/java:openjdk-7-jdk"
+    ],
+    "Size": 0,
+    "VirtualSize": 755313702
+  },
+  {
+    "Created": 1414108439,
+    "Id": "5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5",
+    "ParentId": "22093c35d77bb609b9257ffb2640845ec05018e3d96cb939f68d0e19127f1723",
+    "RepoTags": [
+      "ubuntu:14.04"
+    ],
+    "Size": 0,
+    "VirtualSize": 199257566
+  }
+]
\ No newline at end of file