You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/11/04 04:28:22 UTC
[2/2] git commit: JCLOUDS-737 update docker to support v1.3
JCLOUDS-737 update docker to support v1.3
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/e3c6a6f5
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/e3c6a6f5
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/e3c6a6f5
Branch: refs/heads/master
Commit: e3c6a6f5a7b26badaa385a2ba626fcb9e386761a
Parents: 933f31b
Author: Andrea Turli <an...@gmail.com>
Authored: Thu Oct 2 18:08:24 2014 +0200
Committer: Adrian Cole <ad...@apache.org>
Committed: Mon Nov 3 19:23:09 2014 -0800
----------------------------------------------------------------------
docker/README.md | 10 +-
docker/pom.xml | 1 +
.../main/java/org/jclouds/docker/DockerApi.java | 20 +-
.../org/jclouds/docker/DockerApiMetadata.java | 12 +-
.../functions/ContainerToNodeMetadata.java | 1 -
.../docker/compute/functions/ImageToImage.java | 2 +
.../compute/options/DockerTemplateOptions.java | 2 +-
.../strategy/DockerComputeServiceAdapter.java | 44 +--
.../docker/config/DockerHttpApiModule.java | 23 ++
.../java/org/jclouds/docker/domain/Config.java | 6 +
.../jclouds/docker/domain/ContainerSummary.java | 49 +++
.../org/jclouds/docker/domain/HostConfig.java | 10 +-
.../java/org/jclouds/docker/domain/Image.java | 3 +-
.../java/org/jclouds/docker/domain/Info.java | 63 ++++
.../java/org/jclouds/docker/domain/Version.java | 11 +-
.../jclouds/docker/features/ContainerApi.java | 157 +++++++++
.../org/jclouds/docker/features/ImageApi.java | 110 ++++++
.../org/jclouds/docker/features/MiscApi.java | 72 ++++
.../org/jclouds/docker/features/RemoteApi.java | 256 --------------
.../docker/suppliers/KeyStoreSupplier.java | 130 +++++++
.../suppliers/SSLContextWithKeysSupplier.java | 77 +++++
.../docker/compute/BaseDockerApiLiveTest.java | 2 +
.../DockerComputeServiceAdapterLiveTest.java | 38 ++-
.../compute/DockerComputeServiceLiveTest.java | 220 ++++++++----
.../functions/ContainerToNodeMetadataTest.java | 6 +
.../compute/functions/ImageToImageTest.java | 1 +
.../docker/features/ContainerApiLiveTest.java | 105 ++++++
.../docker/features/ContainerApiMockTest.java | 248 ++++++++++++++
.../docker/features/ImageApiLiveTest.java | 59 ++++
.../docker/features/ImageApiMockTest.java | 97 ++++++
.../docker/features/MiscApiLiveTest.java | 86 +++++
.../docker/features/MiscApiMockTest.java | 159 +++++++++
.../docker/features/RemoteApiLiveTest.java | 115 -------
.../docker/features/RemoteApiMockTest.java | 337 -------------------
.../docker/internal/BaseDockerMockTest.java | 4 +-
docker/src/test/resources/Dockerfile | 17 +-
docker/src/test/resources/SimpleDockerfile | 18 +
docker/src/test/resources/container.json | 204 ++++++-----
docker/src/test/resources/info.json | 28 ++
docker/src/test/resources/version.json | 9 +
40 files changed, 1892 insertions(+), 920 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/README.md
----------------------------------------------------------------------
diff --git a/docker/README.md b/docker/README.md
index 1c4394a..9b55cbc 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -7,6 +7,10 @@ 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:
+
+ `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`
#How it works
@@ -41,8 +45,8 @@ Please follow these steps to configure your workstation for jclouds-docker:
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 -a -q | xargs docker stop | xargs docker rm`
+
+ `$ docker ps -aq | xargs docker rm -f`
2. remove all the images
- `$ docker images -q | xargs docker rmi`
+ `$ docker images -q | xargs docker rmi -f`
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/pom.xml
----------------------------------------------------------------------
diff --git a/docker/pom.xml b/docker/pom.xml
index 0469d60..b268a83 100644
--- a/docker/pom.xml
+++ b/docker/pom.xml
@@ -131,6 +131,7 @@
<goal>test</goal>
</goals>
<configuration>
+ <threadCount>1</threadCount>
<systemPropertyVariables>
<test.docker.endpoint>${test.docker.endpoint}</test.docker.endpoint>
<test.docker.api-version>${test.docker.api-version}</test.docker.api-version>
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/main/java/org/jclouds/docker/DockerApi.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/DockerApi.java b/docker/src/main/java/org/jclouds/docker/DockerApi.java
index 54bf5c9..502f577 100644
--- a/docker/src/main/java/org/jclouds/docker/DockerApi.java
+++ b/docker/src/main/java/org/jclouds/docker/DockerApi.java
@@ -16,22 +16,22 @@
*/
package org.jclouds.docker;
-import org.jclouds.docker.features.RemoteApi;
+import org.jclouds.docker.features.ContainerApi;
+import org.jclouds.docker.features.ImageApi;
+import org.jclouds.docker.features.MiscApi;
import org.jclouds.rest.annotations.Delegate;
import java.io.Closeable;
-/**
- * Provides synchronous access to Docker Remote API.
- *
- * @see <a href="https://docs.docker.com/reference/api/docker_remote_api/"></a>
- */
public interface DockerApi extends Closeable {
- /**
- * Provides synchronous access to Docker Remote API features.
- */
@Delegate
- RemoteApi getRemoteApi();
+ MiscApi getMiscApi();
+
+ @Delegate
+ ContainerApi getContainerApi();
+
+ @Delegate
+ ImageApi getImageApi();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 a533614..d5c470f 100644
--- a/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
+++ b/docker/src/main/java/org/jclouds/docker/DockerApiMetadata.java
@@ -56,7 +56,7 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
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,osVersionMatches=1[012].[01][04]");
+ properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
return properties;
}
@@ -66,16 +66,16 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
super(DockerApi.class);
id("docker")
.name("Docker API")
- .identityName("user")
- .credentialName("password")
+ .identityName("Path to Certificate .p12 file")
+ .credentialName("Password to Certificate")
.documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
- .version("1.12")
- .defaultEndpoint("http://127.0.0.1:2375")
+ .version("1.15")
+ .defaultEndpoint("https://127.0.0.1:2376")
.defaultProperties(DockerApiMetadata.defaultProperties())
.view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(
- DockerHttpApiModule.class,
DockerParserModule.class,
+ DockerHttpApiModule.class,
DockerComputeServiceContextModule.class));
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/main/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadata.java b/docker/src/main/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadata.java
index 7b070fb..20df6a3 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadata.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/functions/ContainerToNodeMetadata.java
@@ -100,7 +100,6 @@ public class ContainerToNodeMetadata implements Function<Container, NodeMetadata
Image image = images.get().get(imageId);
builder.operatingSystem(image.getOperatingSystem());
}
-
return builder.build();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/main/java/org/jclouds/docker/compute/functions/ImageToImage.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/functions/ImageToImage.java b/docker/src/main/java/org/jclouds/docker/compute/functions/ImageToImage.java
index 551c441..7e9de03 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/functions/ImageToImage.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/functions/ImageToImage.java
@@ -19,6 +19,7 @@ package org.jclouds.docker.compute.functions;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
+
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
@@ -44,6 +45,7 @@ public class ImageToImage implements Function<org.jclouds.docker.domain.Image, o
@Override
public Image apply(org.jclouds.docker.domain.Image from) {
checkNotNull(from, "image");
+
String description = checkNotNull(Iterables.getFirst(from.repoTags(), "image must have at least one repo tag"));
OsFamily osFamily = osFamily().apply(description);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
index 9568f33..355c617 100644
--- a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
+++ b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java
@@ -215,7 +215,7 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
}
/**
- * @see DockerTemplateOptions#memory(int)
+ * @see DockerTemplateOptions#memory
*/
public static DockerTemplateOptions memory(int memory) {
DockerTemplateOptions options = new DockerTemplateOptions();
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 fa83ffc..4cbb3b0 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
@@ -37,6 +37,7 @@ import org.jclouds.docker.DockerApi;
import org.jclouds.docker.compute.options.DockerTemplateOptions;
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.options.ListContainerOptions;
@@ -78,7 +79,7 @@ public class DockerComputeServiceAdapter implements
String imageId = checkNotNull(template.getImage().getId(), "template image id must not be null");
String loginUser = template.getImage().getDefaultCredentials().getUser();
- String loginUserPassword = template.getImage().getDefaultCredentials().getPassword();
+ String loginUserPassword = template.getImage().getDefaultCredentials().getOptionalPassword().or("password");
DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(template.getOptions());
int[] inboundPorts = templateOptions.getInboundPorts();
@@ -119,10 +120,15 @@ public class DockerComputeServiceAdapter implements
}
containerConfigBuilder.volumes(volumes);
}
+
+ if (templateOptions.getEnv().isPresent()) {
+ containerConfigBuilder.env(templateOptions.getEnv().get());
+ }
+
Config containerConfig = containerConfigBuilder.build();
logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
- Container container = api.getRemoteApi().createContainer(name, containerConfig);
+ Container container = api.getContainerApi().createContainer(name, containerConfig);
logger.trace("<< container(%s)", container.id());
HostConfig.Builder hostConfigBuilder = HostConfig.builder()
@@ -140,13 +146,13 @@ public class DockerComputeServiceAdapter implements
}
HostConfig hostConfig = hostConfigBuilder.build();
- api.getRemoteApi().startContainer(container.id(), hostConfig);
- container = api.getRemoteApi().inspectContainer(container.id());
+ api.getContainerApi().startContainer(container.id(), hostConfig);
+ container = api.getContainerApi().inspectContainer(container.id());
if (container.state().exitCode() != 0) {
destroyNode(container.id());
throw new IllegalStateException(String.format("Container %s has not started correctly", container.id()));
}
- return new NodeAndInitialCredentials<Container>(container, container.id(),
+ return new NodeAndInitialCredentials(container, container.id(),
LoginCredentials.builder().user(loginUser).password(loginUserPassword).build());
}
@@ -156,21 +162,21 @@ public class DockerComputeServiceAdapter implements
// todo they are only placeholders at the moment
hardware.add(new HardwareBuilder().ids("micro").hypervisor("lxc").name("micro").processor(new Processor(1, 1)).ram(512).build());
hardware.add(new HardwareBuilder().ids("small").hypervisor("lxc").name("small").processor(new Processor(1, 1)).ram(1024).build());
- hardware.add(new HardwareBuilder().ids("medium").hypervisor("lxc").name("medium").processor(new Processor(1, 1)).ram(2048).build());
- hardware.add(new HardwareBuilder().ids("large").hypervisor("lxc").name("large").processor(new Processor(1, 1)).ram(3072).build());
+ hardware.add(new HardwareBuilder().ids("medium").hypervisor("lxc").name("medium").processor(new Processor(2, 1)).ram(2048).build());
+ hardware.add(new HardwareBuilder().ids("large").hypervisor("lxc").name("large").processor(new Processor(2, 1)).ram(3072).build());
return hardware;
}
@Override
public Set<Image> listImages() {
Set<Image> images = Sets.newHashSet();
- for (Image image : api.getRemoteApi().listImages()) {
+ for (Image image : api.getImageApi().listImages()) {
// less efficient than just listImages but returns richer json that needs repoTags coming from listImages
- Image inspected = api.getRemoteApi().inspectImage(image.id());
+ Image inspected = api.getImageApi().inspectImage(image.id());
if (inspected.repoTags().isEmpty()) {
- inspected = Image.create(inspected.id(), inspected.parent(), inspected.created(), inspected.container(),
- inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
- inspected.virtualSize(), image.repoTags());
+ inspected = Image.create(inspected.id(), inspected.parent(), inspected.container(), inspected.created(),
+ inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
+ inspected.virtualSize(), image.repoTags());
}
images.add(inspected);
}
@@ -192,9 +198,9 @@ public class DockerComputeServiceAdapter implements
@Override
public Iterable<Container> listNodes() {
Set<Container> containers = Sets.newHashSet();
- for (Container container : api.getRemoteApi().listContainers(ListContainerOptions.Builder.all(true))) {
+ for (ContainerSummary containerSummary : api.getContainerApi().listContainers(ListContainerOptions.Builder.all(true))) {
// less efficient than just listNodes but returns richer json
- containers.add(api.getRemoteApi().inspectContainer(container.id()));
+ containers.add(api.getContainerApi().inspectContainer(containerSummary.id()));
}
return containers;
}
@@ -203,7 +209,7 @@ public class DockerComputeServiceAdapter implements
public Iterable<Container> listNodesByIds(final Iterable<String> ids) {
Set<Container> containers = Sets.newHashSet();
for (String id : ids) {
- containers.add(api.getRemoteApi().inspectContainer(id));
+ containers.add(api.getContainerApi().inspectContainer(id));
}
return containers;
}
@@ -215,18 +221,18 @@ public class DockerComputeServiceAdapter implements
@Override
public Container getNode(String id) {
- return api.getRemoteApi().inspectContainer(id);
+ return api.getContainerApi().inspectContainer(id);
}
@Override
public void destroyNode(String id) {
- api.getRemoteApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
+ api.getContainerApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
}
@Override
public void rebootNode(String id) {
- api.getRemoteApi().stopContainer(id);
- api.getRemoteApi().startContainer(id);
+ api.getContainerApi().stopContainer(id);
+ api.getContainerApi().startContainer(id);
}
@Override
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 e6da554..ced396c 100644
--- a/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
+++ b/docker/src/main/java/org/jclouds/docker/config/DockerHttpApiModule.java
@@ -16,8 +16,14 @@
*/
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;
@@ -25,6 +31,9 @@ import org.jclouds.http.annotation.ServerError;
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.
*/
@@ -37,4 +46,18 @@ public class DockerHttpApiModule extends HttpApiModule<DockerApi> {
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DockerErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(DockerErrorHandler.class);
}
+
+ /**
+ * This configures SSL certificate authentication when the Docker daemon is set to use an encrypted TCP socket
+ */
+ @Override
+ protected void configure() {
+ super.configure();
+ bind(new TypeLiteral<Supplier<SSLContext>>() {
+ }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
+ });
+ bind(new TypeLiteral<Supplier<KeyStore>>() {
+ }).to(new TypeLiteral<KeyStoreSupplier>() {
+ });
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 396ab2f..bef8969 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Config.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Config.java
@@ -123,6 +123,7 @@ public abstract class Config {
private List<String> entrypoint = ImmutableList.of();
private boolean networkDisabled;
private List<String> onBuild = ImmutableList.of();
+ private Map<String, String> restartPolicy = ImmutableMap.of();
public Builder hostname(String hostname) {
this.hostname = hostname;
@@ -239,6 +240,11 @@ public abstract class Config {
return this;
}
+ public Builder restartPolicy(Map<String, String> restartPolicy) {
+ this.restartPolicy = ImmutableMap.copyOf(restartPolicy);
+ 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,
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..17d0064
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/domain/ContainerSummary.java
@@ -0,0 +1,49 @@
+/*
+ * 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 Container value class)
+@AutoValue
+public abstract class ContainerSummary {
+
+ public abstract String id();
+
+ public abstract List<String> names();
+
+ public abstract String created();
+
+ public abstract String image();
+
+ public abstract String command();
+
+ public abstract List<Port> ports();
+
+ public abstract String status();
+
+ @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/e3c6a6f5/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 757157c..630be7c 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/HostConfig.java
@@ -35,7 +35,7 @@ public abstract class HostConfig {
public abstract List<String> binds();
- public abstract Map<String, String> lxcConf();
+ public abstract List<Map<String, String>> lxcConf();
public abstract boolean privileged();
@@ -53,7 +53,7 @@ public abstract class HostConfig {
@SerializedNames({ "ContainerIDFile", "Binds", "LxcConf", "Privileged", "Dns", "DnsSearch", "PortBindings",
"Links", "PublishAllPorts", "VolumesFrom" })
- public static HostConfig create(String containerIDFile, List<String> binds, Map<String, String> lxcConf,
+ public static HostConfig create(String containerIDFile, List<String> binds, List<Map<String, String>> lxcConf,
boolean privileged, String dns, String dnsSearch, Map<String, List<Map<String, String>>> portBindings,
List<String> links, boolean publishAllPorts, List<String> volumesFrom) {
return new AutoValue_HostConfig(containerIDFile, copyOf(binds), copyOf(lxcConf), privileged, dns, dnsSearch,
@@ -72,7 +72,7 @@ public abstract class HostConfig {
private String containerIDFile;
private List<String> binds = Lists.newArrayList();
- private Map<String, String> lxcConf = Maps.newLinkedHashMap();
+ private List<Map<String, String>> lxcConf = Lists.newArrayList();
private boolean privileged;
private String dns;
private String dnsSearch;
@@ -91,8 +91,8 @@ public abstract class HostConfig {
return this;
}
- public Builder lxcConf(Map<String, String> lxcConf) {
- this.lxcConf.putAll(checkNotNull(lxcConf, "lxcConf"));
+ public Builder lxcConf(List<Map<String, String>> lxcConf) {
+ this.lxcConf.addAll(checkNotNull(lxcConf, "lxcConf"));
return this;
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 99b2594..c80e448 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Image.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Image.java
@@ -48,10 +48,11 @@ public abstract class Image {
public abstract List<String> repoTags();
@SerializedNames({ "Id", "Parent", "Created", "Container", "DockerVersion", "Architecture", "Os", "Size",
- "VirtualSize", "RepoTags", "Architecture" })
+ "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));
}
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..596c0a5
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/domain/Info.java
@@ -0,0 +1,63 @@
+/*
+ * 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 Info {
+
+ public abstract int containers();
+
+ public abstract int images();
+
+ public abstract String driver();
+
+ public abstract String executionDriver();
+
+ public abstract String kernelVersion();
+
+ public abstract int debug();
+
+ public abstract int nFd();
+
+ public abstract int nGoroutines();
+
+ public abstract int nEventsListener();
+
+ public abstract String initPath();
+
+ public abstract String indexServerAddress();
+
+ public abstract int memoryLimit();
+
+ public abstract int swapLimit();
+
+ public abstract int iPv4Forwarding();
+
+ @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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 ee0ba19..7cf7960 100644
--- a/docker/src/main/java/org/jclouds/docker/domain/Version.java
+++ b/docker/src/main/java/org/jclouds/docker/domain/Version.java
@@ -22,6 +22,9 @@ import com.google.auto.value.AutoValue;
@AutoValue
public abstract class Version {
+
+ public abstract String apiVersion();
+
public abstract String arch();
public abstract String gitCommit();
@@ -34,9 +37,9 @@ public abstract class Version {
public abstract String version();
- @SerializedNames({ "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
- public static Version create(String arch, String gitCommit, String goVersion, String kernelVersion, String os,
- String version) {
- return new AutoValue_Version(arch, gitCommit, goVersion, kernelVersion, os, 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) {
+ return new AutoValue_Version(apiVersion, arch, gitCommit, goVersion, kernelVersion, os, version);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..60f7749
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/features/ContainerApi.java
@@ -0,0 +1,157 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks;
+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.options.CommitOptions;
+import org.jclouds.docker.options.ListContainerOptions;
+import org.jclouds.docker.options.RemoveContainerOptions;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+@Consumes(MediaType.APPLICATION_JSON)
+public interface ContainerApi {
+
+ /**
+ * List all running containers
+ *
+ * @return a set of containers
+ */
+ @Named("containers:list")
+ @GET
+ @Path("/containers/json")
+ @Fallback(Fallbacks.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)
+ 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
+ */
+ @Named("container:create")
+ @POST
+ @Path("/containers/create")
+ Container createContainer(@QueryParam("name") String name, @BinderParam(BindToJsonPayload.class) Config config);
+
+ /**
+ * Return low-level information on the container id
+ * @param containerId The id of the container to get.
+ * @return The details of the container or <code>null</code> if the container with the given id doesn't exist.
+ */
+ @Named("container:inspect")
+ @GET
+ @Path("/containers/{id}/json")
+ @Fallback(Fallbacks.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")
+ @DELETE
+ @Path("/containers/{id}")
+ 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)
+ */
+ @Named("container:delete")
+ @DELETE
+ @Path("/containers/{id}")
+ 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")
+ @POST
+ @Path("/containers/{id}/start")
+ 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
+ */
+ @Named("container:start")
+ @POST
+ @Path("/containers/{id}/start")
+ 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);
+
+ /**
+ * Create a new image from a container’s changes
+ *
+ * @param options the commit’s configuration (@see CommitOptions)
+ * @return a new image created from the current container's status.
+ */
+ @Named("container:commit")
+ @POST
+ @Path("/commit")
+ Image commit(CommitOptions options);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..95c963c
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/features/ImageApi.java
@@ -0,0 +1,110 @@
+/*
+ * 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.features;
+
+import java.io.InputStream;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.options.CreateImageOptions;
+import org.jclouds.docker.options.DeleteImageOptions;
+import org.jclouds.docker.options.ListImageOptions;
+import org.jclouds.rest.annotations.Fallback;
+
+@Consumes(MediaType.APPLICATION_JSON)
+public interface ImageApi {
+
+ /**
+ * List images
+ *
+ * @return the images available.
+ */
+ @Named("images:list")
+ @GET
+ @Path("/images/json")
+ @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+ List<Image> 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);
+
+ /**
+ * 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)
+ Image inspectImage(@PathParam("name") String imageName);
+
+ /**
+ * Create an image, either by pull it from the registry or by importing it
+ *
+ * @param options the configuration to create an image (@see CreateImageOptions)
+ * @return a stream of the image creation.
+ */
+ @Named("image:create")
+ @POST
+ @Path("/images/create")
+ InputStream createImage(CreateImageOptions options);
+
+ /**
+ * Delete an image.
+ *
+ * @param name the image name to be deleted
+ * @return the stream of the deletion execution.
+ */
+ @Named("image:delete")
+ @DELETE
+ @Path("/images/{name}")
+ 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.
+ */
+ @Named("image:delete")
+ @DELETE
+ @Path("/images/{name}")
+ InputStream deleteImage(@PathParam("name") String name, DeleteImageOptions options);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..30cd1f3
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/features/MiscApi.java
@@ -0,0 +1,72 @@
+/*
+ * 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.features;
+
+import java.io.InputStream;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.docker.domain.Info;
+import org.jclouds.docker.domain.Version;
+import org.jclouds.docker.options.BuildOptions;
+import org.jclouds.io.Payload;
+import org.jclouds.rest.annotations.Headers;
+
+@Consumes(MediaType.APPLICATION_JSON)
+public interface MiscApi {
+
+ /**
+ * Get the information of the current docker version.
+ *
+ * @return The information of the current docker version.
+ */
+ @Named("version")
+ @GET
+ @Path("/version")
+ Version getVersion();
+
+ /**
+ * Get the information of the current docker version.
+ *
+ * @return The information of the current docker version.
+ */
+ @Named("info")
+ @GET
+ @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.
+ * @param options the image build's options (@see BuildOptions)
+ * @return a stream of the build execution
+ */
+ @Named("image:build")
+ @POST
+ @Path("/build")
+ @Headers(keys = "Content-Type", values = "application/tar")
+ InputStream build(Payload inputStream, BuildOptions options);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/main/java/org/jclouds/docker/features/RemoteApi.java
----------------------------------------------------------------------
diff --git a/docker/src/main/java/org/jclouds/docker/features/RemoteApi.java b/docker/src/main/java/org/jclouds/docker/features/RemoteApi.java
deleted file mode 100644
index 785eb20..0000000
--- a/docker/src/main/java/org/jclouds/docker/features/RemoteApi.java
+++ /dev/null
@@ -1,256 +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.features;
-
-import java.io.Closeable;
-import java.io.InputStream;
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks;
-import org.jclouds.docker.domain.Config;
-import org.jclouds.docker.domain.Container;
-import org.jclouds.docker.domain.HostConfig;
-import org.jclouds.docker.domain.Image;
-import org.jclouds.docker.domain.Version;
-import org.jclouds.docker.options.BuildOptions;
-import org.jclouds.docker.options.CommitOptions;
-import org.jclouds.docker.options.CreateImageOptions;
-import org.jclouds.docker.options.DeleteImageOptions;
-import org.jclouds.docker.options.ListContainerOptions;
-import org.jclouds.docker.options.ListImageOptions;
-import org.jclouds.docker.options.RemoveContainerOptions;
-import org.jclouds.io.Payload;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-@Consumes(MediaType.APPLICATION_JSON)
-public interface RemoteApi extends Closeable {
-
- /**
- * Get the information of the current docker version.
- *
- * @return The information of the current docker version.
- */
- @Named("version")
- @GET
- @Path("/version")
- Version getVersion();
-
- /**
- * List all running containers
- *
- * @return a set of containers
- */
- @Named("containers:list")
- @GET
- @Path("/containers/json")
- @Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
- Set<Container> 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.EmptySetOnNotFoundOr404.class)
- Set<Container> 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
- */
- @Named("container:create")
- @POST
- @Path("/containers/create")
- Container createContainer(@QueryParam("name") String name, @BinderParam(BindToJsonPayload.class) Config config);
-
- /**
- * Return low-level information on the container id
- * @param containerId The id of the container to get.
- * @return The details of the container or <code>null</code> if the container with the given id doesn't exist.
- */
- @Named("container:inspect")
- @GET
- @Path("/containers/{id}/json")
- @Fallback(Fallbacks.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")
- @DELETE
- @Path("/containers/{id}")
- 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)
- */
- @Named("container:delete")
- @DELETE
- @Path("/containers/{id}")
- 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")
- @POST
- @Path("/containers/{id}/start")
- 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
- */
- @Named("container:start")
- @POST
- @Path("/containers/{id}/start")
- 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);
-
- /**
- * Create a new image from a container’s changes
- *
- * @param options the commit’s configuration (@see CommitOptions)
- * @return a new image created from the current container's status.
- */
- @Named("container:commit")
- @POST
- @Path("/commit")
- Image commit(CommitOptions options);
-
- /**
- * List images
- *
- * @return the images available.
- */
- @Named("images:list")
- @GET
- @Path("/images/json")
- @Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
- Set<Image> 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.EmptySetOnNotFoundOr404.class)
- Set<Image> 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")
- Image inspectImage(@PathParam("name") String imageName);
-
- /**
- * Create an image, either by pull it from the registry or by importing it
- *
- * @param options the configuration to create an image (@see CreateImageOptions)
- * @return a stream of the image creation.
- */
- @Named("image:create")
- @POST
- @Path("/images/create")
- InputStream createImage(CreateImageOptions options);
-
- /**
- * Delete an image.
- *
- * @param name the image name to be deleted
- * @return the stream of the deletion execution.
- */
- @Named("image:delete")
- @DELETE
- @Path("/images/{name}")
- 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.
- */
- @Named("image:delete")
- @DELETE
- @Path("/images/{name}")
- InputStream deleteImage(@PathParam("name") String name, DeleteImageOptions options);
-
- /**
- * 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.
- * @param options the image build's options (@see BuildOptions)
- * @return a stream of the build execution
- */
- @Named("image:build")
- @POST
- @Path("/build")
- @Headers(keys = "Content-Type", values = "application/tar")
- InputStream build(Payload inputStream, BuildOptions options);
-}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..e8643cd
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/suppliers/KeyStoreSupplier.java
@@ -0,0 +1,130 @@
+/*
+ * 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/e3c6a6f5/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
new file mode 100644
index 0000000..59695d3
--- /dev/null
+++ b/docker/src/main/java/org/jclouds/docker/suppliers/SSLContextWithKeysSupplier.java
@@ -0,0 +1,77 @@
+/*
+ * 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.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+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.Supplier;
+
+@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;
+ 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;
+ } catch (NoSuchAlgorithmException e) {
+ throw propagate(e);
+ } catch (UnrecoverableKeyException e) {
+ throw propagate(e);
+ } catch (KeyStoreException e) {
+ throw propagate(e);
+ } catch (KeyManagementException e) {
+ throw propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 54f61a1..9aca266 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/BaseDockerApiLiveTest.java
@@ -31,6 +31,7 @@ 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;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
@@ -58,6 +59,7 @@ public class BaseDockerApiLiveTest extends BaseApiLiveTest<DockerApi> {
Properties overrides = super.setupProperties();
overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "15");
overrides.setProperty("jclouds.ssh.retry-auth", "true");
+ overrides.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
return overrides;
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 b64dace..c3da551 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceAdapterLiveTest.java
@@ -22,17 +22,24 @@ import static org.testng.Assert.assertNotNull;
import java.util.Properties;
import java.util.Random;
+import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.docker.DockerApi;
+import org.jclouds.docker.compute.options.DockerTemplateOptions;
import org.jclouds.docker.compute.strategy.DockerComputeServiceAdapter;
import org.jclouds.docker.domain.Container;
+import org.jclouds.docker.domain.Image;
+import org.jclouds.docker.options.CreateImageOptions;
+import org.jclouds.docker.options.DeleteImageOptions;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
@@ -41,27 +48,47 @@ import com.google.inject.Module;
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceAdapterLiveTest")
public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
+ private static final String SSHABLE_IMAGE = "tutum/ubuntu";
+ private static final String SSHABLE_IMAGE_TAG = "trusty";
+ private Image defaultImage;
+
private DockerComputeServiceAdapter adapter;
private TemplateBuilder templateBuilder;
+ private ComputeService computeService;
private NodeAndInitialCredentials<Container> guest;
+ @BeforeClass
+ protected void init() {
+ super.initialize();
+ String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
+ Image image = api.getImageApi().inspectImage(imageName);
+ if (image == null) {
+ CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
+ api.getImageApi().createImage(options);
+ }
+ defaultImage = api.getImageApi().inspectImage(imageName);
+ assertNotNull(defaultImage);
+ }
+
@Override
protected DockerApi create(Properties props, Iterable<Module> modules) {
Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
adapter = injector.getInstance(DockerComputeServiceAdapter.class);
templateBuilder = injector.getInstance(TemplateBuilder.class);
+ computeService = injector.getInstance(ComputeService.class);
return injector.getInstance(DockerApi.class);
}
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
- String name = "container-" + new Random().nextInt();
+ String name = "container" + new Random().nextInt();
- Template template = templateBuilder.smallest()
- .osDescriptionMatches("jclouds/default:latest").build();
+ Template template = templateBuilder.imageId(defaultImage.id()).build();
+ DockerTemplateOptions options = template.getOptions().as(DockerTemplateOptions.class);
+ options.env(ImmutableList.of("ROOT_PASS=password"));
guest = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
- assertEquals(guest.getNodeId(), guest.getNode().id() + "");
+ assertEquals(guest.getNodeId(), guest.getNode().id());
}
public void testListHardwareProfiles() {
@@ -78,6 +105,9 @@ public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
if (guest != null) {
adapter.destroyNode(guest.getNode().id() + "");
}
+ if (defaultImage != null) {
+ api.getImageApi().deleteImage(defaultImage.id(), DeleteImageOptions.Builder.force(true));
+ }
super.tearDown();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceLiveTest.java b/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceLiveTest.java
index cc460c3..1e024e4 100644
--- a/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceLiveTest.java
+++ b/docker/src/test/java/org/jclouds/docker/compute/DockerComputeServiceLiveTest.java
@@ -16,30 +16,67 @@
*/
package org.jclouds.docker.compute;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.lang.String.format;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.logging.Logger.getAnonymousLogger;
+import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask;
+import static org.jclouds.compute.options.TemplateOptions.Builder.runAsRoot;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.JettyStatements;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.compute.util.OpenSocketFinder;
+import org.jclouds.docker.DockerApi;
+import org.jclouds.docker.compute.options.DockerTemplateOptions;
+import org.jclouds.docker.domain.Container;
+import org.jclouds.docker.features.ImageApi;
+import org.jclouds.docker.options.CreateImageOptions;
+import org.jclouds.docker.options.DeleteImageOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.predicates.SocketOpen;
+import org.jclouds.scriptbuilder.domain.Statement;
+import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
import com.google.inject.Module;
/**
* Live tests for the {@link org.jclouds.compute.ComputeService} integration.
*/
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceLiveTest")
-public class DockerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
+public class DockerComputeServiceLiveTest extends BaseComputeServiceContextLiveTest {
- private static final String DEFAULT_JCLOUDS_IMAGE = "jclouds/default";
+ private static final String SSHABLE_IMAGE = "tutum/ubuntu";
+ private static final String SSHABLE_IMAGE_TAG = "trusty";
private Image defaultImage;
+ protected Template template;
+ protected Predicate<HostAndPort> socketTester;
+ protected OpenSocketFinder openSocketFinder;
+
+ protected ComputeService client;
public DockerComputeServiceLiveTest() {
provider = "docker";
@@ -50,93 +87,134 @@ public class DockerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return new SshjSshClientModule();
}
+ @BeforeGroups(groups = { "integration", "live" })
@Override
- protected void initializeContext() {
- super.initializeContext();
- Optional<? extends Image> optionalImage = Iterables.tryFind(client.listImages(), new Predicate<Image>() {
- @Override
- public boolean apply(Image image) {
- return image.getName().equals(DEFAULT_JCLOUDS_IMAGE);
- }
- });
- if (optionalImage.isPresent()) {
- defaultImage = optionalImage.get();
- } else {
- Assert.fail("Please create an ssh-able image called " + DEFAULT_JCLOUDS_IMAGE);
- }
- }
-
- @Override
- protected Template buildTemplate(TemplateBuilder templateBuilder) {
- return templateBuilder.imageId(defaultImage.getId()).build();
+ public void setupContext() {
+ super.setupContext();
+ buildSocketTester();
}
@Override
- public void testOptionToNotBlock() throws Exception {
- // Docker ComputeService implementation has to block until the node
- // is provisioned, to be able to return it.
- }
-
- @Override
- protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
- // Docker does not support tags
- }
+ protected void initializeContext() {
+ super.initializeContext();
+ client = view.getComputeService();
- @Override
- protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
- // Docker does not support user metadata
+ String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
+ org.jclouds.docker.domain.Image image = imageApi().inspectImage(imageName);
+ if (image == null) {
+ CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
+ imageApi().createImage(options);
+ }
+ image = imageApi().inspectImage(imageName);
+ defaultImage = client.getImage(image.id());
+ assertNotNull(defaultImage);
}
+ @AfterClass
@Override
- public void testCreateAndRunAService() throws Exception {
- // Docker does not support blockOnPort
+ protected void tearDownContext() {
+ super.tearDownContext();
+ if (defaultImage != null) {
+ imageApi().deleteImage(SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG, DeleteImageOptions.Builder.force(true));
+ }
}
- @Override
- @Test(enabled = true, dependsOnMethods = { "testCompareSizes" })
- public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
- super.testAScriptExecutionAfterBootWithBasicTemplate();
+ private ImageApi imageApi() {
+ return client.getContext().unwrapApi(DockerApi.class).getImageApi();
}
- @Override
- @Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class)
- public void testSuspendResume() throws Exception {
- super.testSuspendResume();
- }
+ protected Template buildTemplate(TemplateBuilder templateBuilder) {
- @Override
- @Test(enabled = true, dependsOnMethods = "testSuspendResume")
- public void testGetNodesWithDetails() throws Exception {
- super.testGetNodesWithDetails();
+ String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
+ org.jclouds.docker.domain.Image image = imageApi().inspectImage(imageName);
+ if (image == null) {
+ CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
+ imageApi().createImage(options);
+ }
+ image = imageApi().inspectImage(imageName);
+ defaultImage = client.getImage(image.id());
+
+
+ DockerTemplateOptions options = new DockerTemplateOptions();
+ options.env(ImmutableList.of("ROOT_PASS=password"));
+ options.overrideLoginCredentials(LoginCredentials.builder().identity("root").credential("password").build());
+ template = templateBuilder.imageId(defaultImage.getId()).options(options).build();
+ return template;
+ }
+
+ protected void createAndRunAServiceInGroup(String group) throws RunNodesException {
+ // note that some cloud providers do not support mixed case tag names
+ ImmutableMap<String, String> userMetadata = ImmutableMap.of("test", group);
+ ImmutableSet<String> tags = ImmutableSet.of(group);
+ Stopwatch watch = Stopwatch.createStarted();
+ template = buildTemplate(client.templateBuilder());
+ template.getOptions().inboundPorts(22, 8080).blockOnPort(22, 300).userMetadata(userMetadata).tags(tags);
+ NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template));
+ long createSeconds = watch.elapsed(TimeUnit.SECONDS);
+ final String nodeId = node.getId();
+ //checkUserMetadataContains(node, userMetadata);
+ //checkTagsInNodeEquals(node, tags);
+ getAnonymousLogger().info(
+ format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
+ watch.reset().start();
+ client.runScriptOnNode(nodeId, JettyStatements.install(), nameTask("configure-jetty"));
+ long configureSeconds = watch.elapsed(TimeUnit.SECONDS);
+ getAnonymousLogger().info(
+ format(
+ "<< configured node(%s) with %s and jetty %s in %ss",
+ nodeId,
+ exec(nodeId, "java -fullversion"),
+ exec(nodeId, JettyStatements.version()), configureSeconds));
+ trackProcessOnNode(JettyStatements.start(), "start jetty", node);
+ client.runScriptOnNode(nodeId, JettyStatements.stop(), runAsRoot(false).wrapInInitScript(false));
+ trackProcessOnNode(JettyStatements.start(), "start jetty", node);
+ }
+
+ protected void trackProcessOnNode(Statement process, String processName, NodeMetadata node) {
+ ServiceStats stats = new ServiceStats();
+ Stopwatch watch = Stopwatch.createStarted();
+ ExecResponse exec = client.runScriptOnNode(node.getId(), process, runAsRoot(false).wrapInInitScript(false));
+ stats.backgroundProcessMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
+
+ Container container = client.getContext().unwrapApi(DockerApi.class).getContainerApi().inspectContainer(node.getId());
+ Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
+ int port = Integer.parseInt(getOnlyElement(ports.get("8080/tcp")).get("HostPort"));
+
+ watch.reset().start();
+ HostAndPort socket;
+ try {
+ socket = openSocketFinder.findOpenSocketOnNode(node, port, 600, TimeUnit.SECONDS);
+ } catch (NoSuchElementException e) {
+ throw new NoSuchElementException(format("%s%n%s%s", e.getMessage(), exec.getOutput(), exec.getError()));
+ }
+ stats.socketOpenMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
+ getAnonymousLogger().info(format("<< %s on node(%s)[%s] %s", processName, node.getId(), socket, stats));
}
- @Override
- @Test(enabled = true, dependsOnMethods = "testSuspendResume")
- public void testListNodes() throws Exception {
- super.testListNodes();
- }
+ static class ServiceStats {
+ long backgroundProcessMilliseconds;
+ long socketOpenMilliseconds;
- @Override
- @Test(enabled = true, dependsOnMethods = "testSuspendResume")
- public void testListNodesByIds() throws Exception {
- super.testListNodesByIds();
+ @Override
+ public String toString() {
+ return format("[backgroundProcessMilliseconds=%s, socketOpenMilliseconds=%s]",
+ backgroundProcessMilliseconds, socketOpenMilliseconds);
+ }
}
- @Override
- @Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
- public void testDestroyNodes() {
- super.testDestroyNodes();
+ protected String exec(final String nodeId, String command) {
+ return exec(nodeId, Statements.exec(command));
}
- @Test(enabled = true, expectedExceptions = NullPointerException.class)
- public void testCorrectExceptionRunningNodesNotFound() throws Exception {
- super.testCorrectExceptionRunningNodesNotFound();
+ protected String exec(final String nodeId, Statement command) {
+ return client.runScriptOnNode(nodeId, command, runAsRoot(false).wrapInInitScript(false)).getOutput().trim();
}
- @Test(enabled = true, expectedExceptions = NullPointerException.class)
- public void testCorrectAuthException() throws Exception {
- // Docker does not support authentication yet
- super.testCorrectAuthException();
+ protected void buildSocketTester() {
+ SocketOpen socketOpen = view.utils().injector().getInstance(SocketOpen.class);
+ socketTester = retry(socketOpen, 60, 1, SECONDS);
+ // wait a maximum of 60 seconds for port 8080 to open.
+ openSocketFinder = context.utils().injector().getInstance(OpenSocketFinder.class);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 6e79685..94ee205 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
@@ -43,6 +43,7 @@ import org.jclouds.docker.domain.State;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
+import org.jclouds.domain.LoginCredentials;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -59,6 +60,9 @@ import com.google.inject.Guice;
*/
@Test(groups = "unit", testName = "ContainerToNodeMetadataTest")
public class ContainerToNodeMetadataTest {
+
+ private LoginCredentials credentials;
+
private ContainerToNodeMetadata function;
private Container container;
@@ -164,6 +168,8 @@ public class ContainerToNodeMetadataTest {
}
};
+ credentials = LoginCredentials.builder().user("foo").password("bar").build();
+
function = new ContainerToNodeMetadata(providerMetadata, toPortableStatus(), namingConvention, images, locations);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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 0d35792..76d82ee 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
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableList;
*/
@Test(groups = "unit", testName = "ImageToImageTest")
public class ImageToImageTest {
+
private ImageToImage function;
private org.jclouds.docker.domain.Image image;
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/e3c6a6f5/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
new file mode 100644
index 0000000..44edc57
--- /dev/null
+++ b/docker/src/test/java/org/jclouds/docker/features/ContainerApiLiveTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.features;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.jclouds.docker.compute.BaseDockerApiLiveTest;
+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.options.CreateImageOptions;
+import org.jclouds.docker.options.ListContainerOptions;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = "live", testName = "RemoteApiLiveTest", singleThreaded = true)
+public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
+
+ private Container container = null;
+ protected static final String BUSYBOX_IMAGE_TAG = "busybox:ubuntu-12.04";
+ protected Image image = null;
+
+ @BeforeClass
+ protected void init() {
+ if (api.getImageApi().inspectImage(BUSYBOX_IMAGE_TAG) == null) {
+ CreateImageOptions options = CreateImageOptions.Builder.fromImage(BUSYBOX_IMAGE_TAG);
+ InputStream createImageStream = api.getImageApi().createImage(options);
+ consumeStream(createImageStream);
+ }
+ image = api.getImageApi().inspectImage(BUSYBOX_IMAGE_TAG);
+ assertNotNull(image);
+ }
+
+ @AfterClass
+ protected void tearDown() {
+ if (image != null) {
+ api.getImageApi().deleteImage(BUSYBOX_IMAGE_TAG);
+ }
+ }
+
+ 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"))
+ .build();
+ container = api().createContainer("testCreateContainer", containerConfig);
+ assertNotNull(container);
+ assertNotNull(container.id());
+ }
+
+ @Test(dependsOnMethods = "testCreateContainer")
+ public void testStartContainer() throws IOException, InterruptedException {
+ api().startContainer(container.id());
+ assertTrue(api().inspectContainer(container.id()).state().running());
+ }
+
+ @Test(dependsOnMethods = "testStartContainer")
+ public void testStopContainer() {
+ api().stopContainer(container.id());
+ assertFalse(api().inspectContainer(container.id()).state().running());
+ }
+
+ @Test
+ public void testListContainers() {
+ List<ContainerSummary> containerSummaries = api().listContainers(ListContainerOptions.Builder.all(true));
+ for (ContainerSummary containerSummary : containerSummaries) {
+ assertNotNull(containerSummary.id());
+ assertNotNull(containerSummary.image());
+ assertFalse(containerSummary.names().isEmpty());
+ }
+ }
+
+ @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();
+ }
+}