[JCLOUDS-500] Initial commit for docker

This commit is contained in:
Andrea Turli 2014-01-28 10:42:43 +01:00 committed by Ignasi Barrera
commit 779551c40f
53 changed files with 6346 additions and 0 deletions

48
apis/docker/README.md Normal file
View File

@ -0,0 +1,48 @@
# Docker as a local cloud provider
jclouds-docker is a local cloud provider modelled on [docker](http://www.docker.io). Similar to other jclouds supported
providers, it supports the same portable abstractions offered by jclouds.
##Setup
Please follow these steps to configure your workstation for jclouds-docker:
- install the latest Docker release (please visit https://docs.docker.com/installation/)
#How it works
--------------- -------------
| Image(s) | | Node(s) |
--------------- -------------
--------- docker remote api ----------------------------------------
| jclouds | ---------------------------> | DOCKER_HOST |
--------- ----------------------------------------
##Components
- jclouds \- acts as a java client to access to docker features
- DOCKER_HOST \- hosts Docker API, NB: jclouds-docker assumes that the latest Docker is installed
- Image \- it is a docker image that can be started.
- Node \- is a docker container
## Assumptions
- jclouds-docker assumes that the images specified using the template are ssh'able.
--------------
#Notes:
- jclouds-docker is still at alpha stage please report any issues you find at [jclouds issues](https://issues.apache.org/jira/browse/JCLOUDS)
- jclouds-docker has been tested on Mac OSX, it might work on Linux iff vbox is running and set up correctly. However, it has never been tried on Windows.
--------------
#Troubleshooting
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`
2. remove all the images
`$ docker images -q | xargs docker rmi`

143
apis/docker/pom.xml Normal file
View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.jclouds.labs</groupId>
<artifactId>jclouds-labs</artifactId>
<version>1.8.0-SNAPSHOT</version>
</parent>
<!-- TODO: when out of labs, switch to org.jclouds.provider -->
<groupId>org.apache.jclouds.labs</groupId>
<artifactId>docker</artifactId>
<name>jclouds docker API</name>
<description>ComputeService binding to the Docker API</description>
<packaging>bundle</packaging>
<properties>
<test.docker.endpoint>https://localhost:4243</test.docker.endpoint>
<test.docker.api-version>1.10</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>
<jclouds.osgi.import>
org.jclouds.compute.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
<exclusions>
<!-- Already provided by jclouds-sshj -->
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.docker.endpoint>${test.docker.endpoint}</test.docker.endpoint>
<test.docker.api-version>${test.docker.api-version}</test.docker.api-version>
<test.docker.credential>${test.docker.identity}</test.docker.credential>
<test.docker.credential>${test.docker.credential}</test.docker.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,37 @@
/*
* 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;
import org.jclouds.docker.features.RemoteApi;
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();
}

View File

@ -0,0 +1,98 @@
/*
* 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;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import org.jclouds.Constants;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.docker.compute.config.DockerComputeServiceContextModule;
import org.jclouds.docker.config.DockerHttpApiModule;
import org.jclouds.docker.config.DockerParserModule;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import java.net.URI;
import java.util.Properties;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.reflect.Reflection2.typeToken;
/**
* Implementation of {@link BaseHttpApiMetadata} for the Docker API
*/
public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public DockerApiMetadata() {
this(new Builder());
}
protected DockerApiMetadata(Builder builder) {
super(builder);
}
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,osVersionMatches=1[012].[01][04]");
return properties;
}
public static class Builder extends BaseHttpApiMetadata.Builder<DockerApi, Builder> {
protected Builder() {
super(DockerApi.class);
id("docker")
.name("Docker API")
.identityName("user")
.credentialName("password")
.documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
.version("1.12")
.defaultEndpoint("http://127.0.0.1:2375")
.defaultProperties(DockerApiMetadata.defaultProperties())
.view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(
DockerHttpApiModule.class,
DockerParserModule.class,
DockerComputeServiceContextModule.class));
}
@Override
public DockerApiMetadata build() {
return new DockerApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
@Override
public Builder fromApiMetadata(ApiMetadata in) {
return this;
}
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.binders;
import com.google.common.base.Throwables;
import com.google.common.io.Files;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.docker.features.internal.Archives;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.logging.Logger;
import org.jclouds.rest.Binder;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Singleton
public class BindInputStreamToRequest implements Binder {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof File, "this binder is only valid for File!");
checkNotNull(request, "request");
File dockerFile = (File) input;
File tmpDir = Files.createTempDir();
final File targetFile = new File(tmpDir + File.separator + "Dockerfile");
try {
Files.copy(dockerFile, targetFile);
File archive = Archives.tar(tmpDir, File.createTempFile("archive", ".tar"));
FileInputStream data = new FileInputStream(archive);
Payload payload = Payloads.newInputStreamPayload(data);
payload.getContentMetadata().setContentLength(data.getChannel().size());
payload.getContentMetadata().setContentType("application/tar");
request.setPayload(payload);
} catch (IOException e) {
logger.error(e, "Couldn't create a tarball for %s", targetFile);
throw Throwables.propagate(e);
}
return request;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.compute.config;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.docker.compute.functions.ContainerToNodeMetadata;
import org.jclouds.docker.compute.functions.ImageToImage;
import org.jclouds.docker.compute.functions.StateToStatus;
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.domain.State;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
public class DockerComputeServiceContextModule extends
ComputeServiceAdapterContextModule<Container, Hardware, Image, Location> {
@Override
protected void configure() {
super.configure();
bind(new TypeLiteral<ComputeServiceAdapter<Container, Hardware, Image, Location>>() {
}).to(DockerComputeServiceAdapter.class);
bind(new TypeLiteral<Function<Container, NodeMetadata>>() {
}).to(ContainerToNodeMetadata.class);
bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {
}).to(ImageToImage.class);
bind(new TypeLiteral<Function<Hardware, Hardware>>() {
}).to(Class.class.cast(IdentityFunction.class));
bind(new TypeLiteral<Function<Location, Location>>() {
}).to(Class.class.cast(IdentityFunction.class));
bind(new TypeLiteral<Function<State, NodeMetadata.Status>>() {
}).to(StateToStatus.class);
bind(TemplateOptions.class).to(DockerTemplateOptions.class);
}
}

View File

@ -0,0 +1,126 @@
/*
* 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.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.Port;
import org.jclouds.docker.domain.State;
import org.jclouds.domain.Location;
import org.jclouds.providers.ProviderMetadata;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.inject.Singleton;
@Singleton
public class ContainerToNodeMetadata implements Function<Container, NodeMetadata> {
private final ProviderMetadata providerMetadata;
private final Function<State, NodeMetadata.Status> toPortableStatus;
private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Map<String, ? extends Image>> images;
private final Supplier<Set<? extends Location>> locations;
@Inject
public ContainerToNodeMetadata(ProviderMetadata providerMetadata, Function<State,
NodeMetadata.Status> toPortableStatus, GroupNamingConvention.Factory namingConvention,
Supplier<Map<String, ? extends Image>> images,
@Memoized Supplier<Set<? extends Location>> locations) {
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
this.toPortableStatus = checkNotNull(toPortableStatus, "toPortableStatus cannot be null");
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
this.images = checkNotNull(images, "images cannot be null");
this.locations = checkNotNull(locations, "locations");
}
@Override
public NodeMetadata apply(Container container) {
String name = cleanUpName(container.getName());
String group = nodeNamingConvention.extractGroup(name);
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(container.getId())
.name(name)
.group(group)
.hostname(container.getContainerConfig().getHostname())
// TODO Set up hardware
.hardware(new HardwareBuilder()
.id("")
.ram(container.getContainerConfig().getMemory())
.processor(new Processor(container.getContainerConfig().getCpuShares(), container.getContainerConfig().getCpuShares()))
.build());
builder.status(toPortableStatus.apply(container.getState()));
builder.imageId(container.getImage());
builder.loginPort(getLoginPort(container));
builder.publicAddresses(getPublicIpAddresses());
builder.privateAddresses(getPrivateIpAddresses(container));
builder.location(Iterables.getOnlyElement(locations.get()));
Image image = images.get().get(container.getImage());
builder.imageId(image.getId());
builder.operatingSystem(image.getOperatingSystem());
return builder.build();
}
private String cleanUpName(String name) {
return name.startsWith("/") ? name.substring(1) : name;
}
private Iterable<String> getPrivateIpAddresses(Container container) {
if (container.getNetworkSettings() == null) return ImmutableList.of();
return ImmutableList.of(container.getNetworkSettings().getIpAddress());
}
private List<String> getPublicIpAddresses() {
String dockerIpAddress = URI.create(providerMetadata.getEndpoint()).getHost();
return ImmutableList.of(dockerIpAddress);
}
protected static int getLoginPort(Container container) {
if (container.getNetworkSettings() != null) {
Map<String, List<Map<String, String>>> ports = container.getNetworkSettings().getPorts();
if (ports != null) {
return Integer.parseInt(getOnlyElement(ports.get("22/tcp")).get("HostPort"));
}
// this is needed in case the container list is coming from listContainers
} else if (container.getPorts() != null) {
for (Port port : container.getPorts()) {
if (port.getPrivatePort() == 22) {
return port.getPublicPort();
}
}
}
throw new IllegalStateException("Cannot determine the login port for " + container.getId());
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.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;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import javax.inject.Named;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.get;
public class ImageToImage implements Function<org.jclouds.docker.domain.Image, org.jclouds.compute.domain.Image> {
private static final String CENTOS = "centos";
private static final String UBUNTU = "ubuntu";
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Override
public Image apply(org.jclouds.docker.domain.Image from) {
checkNotNull(from, "image");
String description = checkNotNull(Iterables.getFirst(from.getRepoTags(), "image must have at least one repo tag"));
OsFamily osFamily = osFamily().apply(description);
String osVersion = parseVersion(description);
OperatingSystem os = OperatingSystem.builder()
.description(description)
.family(osFamily)
.version(osVersion)
.is64Bit(is64bit(from))
.build();
return new ImageBuilder()
.ids(from.getId())
.name(get(Splitter.on(":").split(description), 0))
.description(description)
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.build();
}
private boolean is64bit(org.jclouds.docker.domain.Image inspectedImage) {
if (inspectedImage.getArchitecture() == null) return true;
return inspectedImage.getArchitecture().matches("x86_64|amd64");
}
/**
* Parses the item description to determine the OSFamily
*
* @return the @see OsFamily or OsFamily.UNRECOGNIZED
*/
private Function<String, OsFamily> osFamily() {
return new Function<String, OsFamily>() {
@Override
public OsFamily apply(final String description) {
if (description != null) {
if (description.contains(CENTOS)) return OsFamily.CENTOS;
else if (description.contains(UBUNTU)) return OsFamily.UBUNTU;
}
return OsFamily.UNRECOGNIZED;
}
};
}
private String parseVersion(String description) {
String version = get(Splitter.on(":").split(description), 1);
logger.debug("os version for item: %s is %s", description, version);
return version;
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.compute.functions;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.docker.domain.State;
import com.google.common.base.Function;
/**
* Transforms an {@link org.jclouds.docker.domain.Container} to the jclouds portable model.
*/
@Singleton
public class StateToStatus implements Function<State, Status> {
@Override
public Status apply(final State state) {
if (state == null) return Status.UNRECOGNIZED;
return state.isRunning() ? Status.RUNNING : Status.TERMINATED;
}
}

View File

@ -0,0 +1,485 @@
/*
* 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.compute.options;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Contains options supported in the {@code ComputeService#runNode} operation on the
* "docker" provider. <h2>Usage</h2> The recommended way to instantiate a
* DockerTemplateOptions object is to statically import DockerTemplateOptions.* and invoke a static
* creation method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.docker.compute.options.DockerTemplateOptions.Builder.*;
* <p/>
* ComputeService api = // get connection
* templateBuilder.options(inboundPorts(22, 80, 8080, 443));
* Set<? extends NodeMetadata> set = api.createNodesInGroup(tag, 2, templateBuilder.build());
* <code>
*/
public class DockerTemplateOptions extends TemplateOptions implements Cloneable {
protected Optional<String> dns = Optional.absent();
protected Optional<String> hostname = Optional.absent();
protected Optional<Integer> memory = Optional.absent();
protected Optional<Integer> cpuShares = Optional.absent();
protected Optional<List<String>> commands = Optional.absent();
protected Optional<Map<String, String>> volumes = Optional.absent();
@Override
public DockerTemplateOptions clone() {
DockerTemplateOptions options = new DockerTemplateOptions();
copyTo(options);
return options;
}
@Override
public void copyTo(TemplateOptions to) {
super.copyTo(to);
if (to instanceof DockerTemplateOptions) {
DockerTemplateOptions eTo = DockerTemplateOptions.class.cast(to);
if (volumes.isPresent()) {
eTo.volumes(getVolumes().get());
}
if (hostname.isPresent()) {
eTo.hostname(hostname.get());
}
if (dns.isPresent()) {
eTo.dns(dns.get());
}
if (memory.isPresent()) {
eTo.memory(memory.get());
}
if (commands.isPresent()) {
eTo.commands(commands.get());
}
if (cpuShares.isPresent()) {
eTo.cpuShares(cpuShares.get());
}
}
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
DockerTemplateOptions that = DockerTemplateOptions.class.cast(o);
return super.equals(that) && equal(this.volumes, that.volumes) &&
equal(this.hostname, that.hostname) &&
equal(this.dns, that.dns) &&
equal(this.memory, that.memory) &&
equal(this.commands, that.commands) &&
equal(this.cpuShares, that.cpuShares);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), volumes, hostname, dns, memory, commands, cpuShares);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("dns", dns)
.add("hostname", hostname)
.add("memory", memory)
.add("cpuShares", cpuShares)
.add("commands", commands)
.add("volumes", volumes)
.toString();
}
public static final DockerTemplateOptions NONE = new DockerTemplateOptions();
public DockerTemplateOptions volumes(Map<String, String> volumes) {
this.volumes = Optional.<Map<String, String>> of(ImmutableMap.copyOf(volumes));
return this;
}
public TemplateOptions dns(@Nullable String dns) {
this.dns = Optional.fromNullable(dns);
return this;
}
public TemplateOptions hostname(@Nullable String hostname) {
this.hostname = Optional.fromNullable(hostname);
return this;
}
public TemplateOptions memory(@Nullable Integer memory) {
this.memory = Optional.fromNullable(memory);
return this;
}
public TemplateOptions commands(Iterable<String> commands) {
for (String command : checkNotNull(commands, "commands"))
checkNotNull(command, "all commands must be non-empty");
this.commands = Optional.<List<String>> of(ImmutableList.copyOf(commands));
return this;
}
public TemplateOptions commands(String... commands) {
return commands(ImmutableList.copyOf(checkNotNull(commands, "commands")));
}
public TemplateOptions cpuShares(@Nullable Integer cpuShares) {
this.cpuShares = Optional.fromNullable(cpuShares);
return this;
}
public Optional<Map<String, String>> getVolumes() {
return volumes;
}
public Optional<String> getDns() { return dns; }
public Optional<String> getHostname() { return hostname; }
public Optional<Integer> getMemory() { return memory; }
public Optional<List<String>> getCommands() {
return commands;
}
public Optional<Integer> getCpuShares() { return cpuShares; }
public static class Builder {
/**
* @see DockerTemplateOptions#volumes(java.util.Map)
*/
public static DockerTemplateOptions volumes(Map<String, String> volumes) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.volumes(volumes));
}
/**
* @see DockerTemplateOptions#dns(String)
*/
public static DockerTemplateOptions dns(String dns) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.dns(dns));
}
/**
* @see DockerTemplateOptions#hostname(String)
*/
public static DockerTemplateOptions hostname(String hostname) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.hostname(hostname));
}
/**
* @see DockerTemplateOptions#memory(int)
*/
public static DockerTemplateOptions memory(int memory) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.memory(memory));
}
/**
* @see DockerTemplateOptions#commands(Iterable)
*/
public static DockerTemplateOptions commands(String... commands) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.commands(commands));
}
public static DockerTemplateOptions commands(Iterable<String> commands) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.commands(commands));
}
/**
* @see DockerTemplateOptions#cpuShares(int)
*/
public static DockerTemplateOptions cpuShares(int cpuShares) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.cpuShares(cpuShares));
}
// methods that only facilitate returning the correct object type
/**
* @see TemplateOptions#inboundPorts
*/
public static DockerTemplateOptions inboundPorts(int... ports) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.inboundPorts(ports));
}
/**
* @see TemplateOptions#port
*/
public static DockerTemplateOptions blockOnPort(int port, int seconds) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.blockOnPort(port, seconds));
}
/**
* @see TemplateOptions#installPrivateKey
*/
public static DockerTemplateOptions installPrivateKey(String rsaKey) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.installPrivateKey(rsaKey));
}
/**
* @see TemplateOptions#authorizePublicKey
*/
public static DockerTemplateOptions authorizePublicKey(String rsaKey) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.authorizePublicKey(rsaKey));
}
/**
* @see TemplateOptions#userMetadata
*/
public static DockerTemplateOptions userMetadata(Map<String, String> userMetadata) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.userMetadata(userMetadata));
}
/**
* @see TemplateOptions#nodeNames(Iterable)
*/
public static DockerTemplateOptions nodeNames(Iterable<String> nodeNames) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.nodeNames(nodeNames));
}
/**
* @see TemplateOptions#networks(Iterable)
*/
public static DockerTemplateOptions networks(Iterable<String> networks) {
DockerTemplateOptions options = new DockerTemplateOptions();
return DockerTemplateOptions.class.cast(options.networks(networks));
}
/**
* @see TemplateOptions#overrideLoginUser
*/
public static DockerTemplateOptions overrideLoginUser(String user) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.overrideLoginUser(user);
}
/**
* @see TemplateOptions#overrideLoginPassword
*/
public static DockerTemplateOptions overrideLoginPassword(String password) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.overrideLoginPassword(password);
}
/**
* @see TemplateOptions#overrideLoginPrivateKey
*/
public static DockerTemplateOptions overrideLoginPrivateKey(String privateKey) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.overrideLoginPrivateKey(privateKey);
}
/**
* @see TemplateOptions#overrideAuthenticateSudo
*/
public static DockerTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.overrideAuthenticateSudo(authenticateSudo);
}
/**
* @see TemplateOptions#overrideLoginCredentials
*/
public static DockerTemplateOptions overrideLoginCredentials(LoginCredentials credentials) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.overrideLoginCredentials(credentials);
}
/**
* @see TemplateOptions#blockUntilRunning
*/
public static DockerTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
DockerTemplateOptions options = new DockerTemplateOptions();
return options.blockUntilRunning(blockUntilRunning);
}
}
// methods that only facilitate returning the correct object type
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions blockOnPort(int port, int seconds) {
return DockerTemplateOptions.class.cast(super.blockOnPort(port, seconds));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions inboundPorts(int... ports) {
return DockerTemplateOptions.class.cast(super.inboundPorts(ports));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions authorizePublicKey(String publicKey) {
return DockerTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions installPrivateKey(String privateKey) {
return DockerTemplateOptions.class.cast(super.installPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
return DockerTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions dontAuthorizePublicKey() {
return DockerTemplateOptions.class.cast(super.dontAuthorizePublicKey());
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions nameTask(String name) {
return DockerTemplateOptions.class.cast(super.nameTask(name));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions runAsRoot(boolean runAsRoot) {
return DockerTemplateOptions.class.cast(super.runAsRoot(runAsRoot));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions runScript(Statement script) {
return DockerTemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) {
return DockerTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions overrideLoginPassword(String password) {
return DockerTemplateOptions.class.cast(super.overrideLoginPassword(password));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions overrideLoginPrivateKey(String privateKey) {
return DockerTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions overrideLoginUser(String loginUser) {
return DockerTemplateOptions.class.cast(super.overrideLoginUser(loginUser));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
return DockerTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions userMetadata(Map<String, String> userMetadata) {
return DockerTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions userMetadata(String key, String value) {
return DockerTemplateOptions.class.cast(super.userMetadata(key, value));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions nodeNames(Iterable<String> nodeNames) {
return DockerTemplateOptions.class.cast(super.nodeNames(nodeNames));
}
/**
* {@inheritDoc}
*/
@Override
public DockerTemplateOptions networks(Iterable<String> networks) {
return DockerTemplateOptions.class.cast(super.networks(networks));
}
}

View File

@ -0,0 +1,232 @@
/*
* 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.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.reference.ComputeServiceConstants;
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.HostConfig;
import org.jclouds.docker.domain.Image;
import org.jclouds.docker.options.ListContainerOptions;
import org.jclouds.docker.options.RemoveContainerOptions;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* defines the connection between the {@link org.jclouds.docker.DockerApi} implementation and
* the jclouds {@link org.jclouds.compute.ComputeService}
*/
@Singleton
public class DockerComputeServiceAdapter implements
ComputeServiceAdapter<Container, Hardware, Image, Location> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final DockerApi api;
@Inject
public DockerComputeServiceAdapter(DockerApi api) {
this.api = checkNotNull(api, "api");
}
@Override
public NodeAndInitialCredentials<Container> createNodeWithGroupEncodedIntoName(String group, String name,
Template template) {
checkNotNull(template, "template was null");
checkNotNull(template.getOptions(), "template options was null");
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();
DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(template.getOptions());
int[] inboundPorts = templateOptions.getInboundPorts();
Map<String, Object> exposedPorts = Maps.newHashMap();
for (int inboundPort : inboundPorts) {
exposedPorts.put(inboundPort + "/tcp", Maps.newHashMap());
}
Config.Builder containerConfigBuilder = Config.builder()
.imageId(imageId)
.exposedPorts(exposedPorts);
if (templateOptions.getCommands().isPresent()) {
containerConfigBuilder.cmd(templateOptions.getCommands().get());
}
if (templateOptions.getMemory().isPresent()) {
containerConfigBuilder.memory(templateOptions.getMemory().get());
}
if (templateOptions.getCpuShares().isPresent()) {
containerConfigBuilder.cpuShares(templateOptions.getCpuShares().get());
}
if (templateOptions.getVolumes().isPresent()) {
Map<String, Object> volumes = Maps.newLinkedHashMap();
for (String containerDir : templateOptions.getVolumes().get().values()) {
volumes.put(containerDir, Maps.newHashMap());
}
containerConfigBuilder.volumes(volumes);
}
Config containerConfig = containerConfigBuilder.build();
logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
Container container = api.getRemoteApi().createContainer(name, containerConfig);
logger.trace("<< container(%s)", container.getId());
HostConfig.Builder hostConfigBuilder = HostConfig.builder()
.publishAllPorts(true)
.privileged(true);
if (templateOptions.getDns().isPresent()) {
hostConfigBuilder.dns(templateOptions.getDns().get());
}
// set up for volume bindings
if (templateOptions.getVolumes().isPresent()) {
for (Map.Entry<String, String> entry : templateOptions.getVolumes().get().entrySet()) {
hostConfigBuilder.binds(ImmutableList.of(entry.getKey() + ":" + entry.getValue()));
}
}
HostConfig hostConfig = hostConfigBuilder.build();
api.getRemoteApi().startContainer(container.getId(), hostConfig);
container = api.getRemoteApi().inspectContainer(container.getId());
if (container.getState().getExitCode() != 0) {
destroyNode(container.getId());
throw new IllegalStateException(String.format("Container %s has not started correctly", container.getId()));
}
return new NodeAndInitialCredentials<Container>(container, container.getId(),
LoginCredentials.builder().user(loginUser).password(loginUserPassword).build());
}
@Override
public Iterable<Hardware> listHardwareProfiles() {
Set<Hardware> hardware = Sets.newLinkedHashSet();
// 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());
return hardware;
}
@Override
public Set<Image> listImages() {
Set<Image> images = Sets.newHashSet();
for (Image image : api.getRemoteApi().listImages()) {
// less efficient than just listImages but returns richer json that needs repoTags coming from listImages
Image inspected = api.getRemoteApi().inspectImage(image.getId());
if (inspected.getRepoTags().isEmpty()) {
inspected = Image.builder().fromImage(inspected).repoTags(image.getRepoTags()).build();
}
images.add(inspected);
}
return images;
}
@Override
public Image getImage(final String imageId) {
// less efficient than just inspectImage but listImages return repoTags
return find(listImages(), new Predicate<Image>() {
@Override
public boolean apply(Image input) {
return input.getId().equals(imageId);
}
}, null);
}
@Override
public Iterable<Container> listNodes() {
Set<Container> containers = Sets.newHashSet();
for (Container container : api.getRemoteApi().listContainers(ListContainerOptions.Builder.all(true))) {
// less efficient than just listNodes but returns richer json
containers.add(api.getRemoteApi().inspectContainer(container.getId()));
}
return containers;
}
@Override
public Iterable<Container> listNodesByIds(final Iterable<String> ids) {
Set<Container> containers = Sets.newHashSet();
for (String id : ids) {
containers.add(api.getRemoteApi().inspectContainer(id));
}
return containers;
}
@Override
public Iterable<Location> listLocations() {
return ImmutableSet.of();
}
@Override
public Container getNode(String id) {
return api.getRemoteApi().inspectContainer(id);
}
@Override
public void destroyNode(String id) {
api.getRemoteApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
}
@Override
public void rebootNode(String id) {
api.getRemoteApi().stopContainer(id);
api.getRemoteApi().startContainer(id);
}
@Override
public void resumeNode(String id) {
throw new UnsupportedOperationException("resume not supported");
}
@Override
public void suspendNode(String id) {
throw new UnsupportedOperationException("suspend not supported");
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.DockerApi;
import org.jclouds.docker.handlers.DockerErrorHandler;
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.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
/**
* Configures the Docker connection.
*/
@ConfiguresHttpApi
public class DockerHttpApiModule extends HttpApiModule<DockerApi> {
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(DockerErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DockerErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(DockerErrorHandler.class);
}
}

View File

@ -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.config;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.jclouds.docker.domain.Container;
import org.jclouds.json.config.GsonModule;
import javax.inject.Singleton;
import java.lang.reflect.Type;
import java.util.Map;
public class DockerParserModule extends AbstractModule {
@Override
protected void configure() {
bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
}
@Provides
@Singleton
public Map<Type, Object> provideCustomAdapterBindings() {
return new ImmutableMap.Builder<Type, Object>()
.put(Container.class, new ContainerTypeAdapter())
.build();
}
protected static class ContainerTypeAdapter implements JsonDeserializer<Container> {
@Override
public Container deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
Gson gson = new GsonBuilder().serializeNulls().create();
final JsonObject jsonObject = json.getAsJsonObject();
return gson.fromJson(jsonObject, Container.class);
}
}
}

View File

@ -0,0 +1,26 @@
/*
* 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";
}

View File

@ -0,0 +1,457 @@
/*
* 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 com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.SerializedName;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
public class Config {
@SerializedName("Hostname")
private final String hostname;
@SerializedName("Domainname")
private final String domainName;
@SerializedName("User")
private final String user;
@SerializedName("Memory")
private final int memory;
@SerializedName("MemorySwap")
private final int memorySwap;
@SerializedName("CpuShares")
private final int cpuShares;
@SerializedName("AttachStdin")
private final boolean attachStdin;
@SerializedName("AttachStdout")
private final boolean attachStdout;
@SerializedName("AttachStderr")
private final boolean attachStderr;
@SerializedName("ExposedPorts")
private final Map<String, ?> exposedPorts;
@SerializedName("Tty")
private final boolean tty;
@SerializedName("OpenStdin")
private final boolean openStdin;
@SerializedName("StdinOnce")
private final boolean stdinOnce;
@SerializedName("Env")
private final List<String> env;
@SerializedName("Cmd")
private final List<String> cmd;
@SerializedName("Dns")
private final List<String> dns;
@SerializedName("Image")
private final String imageId;
@SerializedName("Volumes")
private final Map<String, ?> volumes;
@SerializedName("VolumesFrom")
private final String volumesFrom;
@SerializedName("WorkingDir")
private final String workingDir;
@SerializedName("Entrypoint")
private final String entrypoint;
@SerializedName("NetworkDisabled")
private final boolean networkDisabled;
@SerializedName("OnBuild")
private final List<String> onBuild;
@ConstructorProperties({ "Hostname", "Domainname", "User", "Memory", "MemorySwap", "CpuShares", "AttachStdin",
"AttachStdout", "AttachStderr", "ExposedPorts", "Tty", "OpenStdin", "StdinOnce", "Env", "Cmd",
"Dns", "Image", "Volumes", "VolumesFrom", "WorkingDir", "Entrypoint", "NetworkDisabled", "OnBuild" })
protected Config(@Nullable String hostname, @Nullable String domainName, @Nullable String user,
int memory, int memorySwap, int cpuShares, boolean attachStdin, boolean attachStdout,
boolean attachStderr, Map<String, ?> exposedPorts, boolean tty, boolean openStdin,
boolean stdinOnce, @Nullable List<String> env, @Nullable List<String> cmd,
@Nullable List<String> dns, String imageId, @Nullable Map<String, ?> volumes,
@Nullable String volumesFrom, @Nullable String workingDir, @Nullable String entrypoint,
@Nullable boolean networkDisabled, @Nullable List<String> onBuild) {
this.hostname = hostname;
this.domainName = domainName;
this.user = user;
this.memory = checkNotNull(memory, "memory");
this.memorySwap = checkNotNull(memorySwap, "memorySwap");
this.cpuShares = checkNotNull(cpuShares, "cpuShares");
this.attachStdin = checkNotNull(attachStdin, "attachStdin");
this.attachStdout = checkNotNull(attachStdout, "attachStdout");
this.attachStderr = checkNotNull(attachStderr, "attachStderr");
this.exposedPorts = exposedPorts != null ? ImmutableMap.copyOf(exposedPorts) : ImmutableMap.<String, Object> of();
this.tty = checkNotNull(tty, "tty");
this.openStdin = checkNotNull(openStdin, "openStdin");
this.stdinOnce = checkNotNull(stdinOnce, "stdinOnce");
this.env = env != null ? ImmutableList.copyOf(env) : ImmutableList.<String> of();
this.cmd = cmd != null ? ImmutableList.copyOf(cmd) : ImmutableList.<String> of();
this.dns = dns != null ? ImmutableList.copyOf(dns) : ImmutableList.<String> of();
this.imageId = checkNotNull(imageId, "imageId");
this.volumes = volumes != null ? ImmutableMap.copyOf(volumes) : ImmutableMap.<String, Object> of();
this.volumesFrom = volumesFrom;
this.workingDir = workingDir;
this.entrypoint = entrypoint;
this.networkDisabled = networkDisabled;
this.onBuild = onBuild != null ? ImmutableList.copyOf(onBuild) : ImmutableList.<String> of();
}
public String getHostname() {
return hostname;
}
public String getDomainName() {
return domainName;
}
public String getUser() {
return user;
}
public int getMemory() {
return memory;
}
public int getMemorySwap() {
return memorySwap;
}
public int getCpuShares() {
return cpuShares;
}
public boolean isAttachStdin() {
return attachStdin;
}
public boolean isAttachStdout() {
return attachStdout;
}
public boolean isAttachStderr() {
return attachStderr;
}
public Map<String, ?> getExposedPorts() {
return exposedPorts;
}
public boolean isTty() {
return tty;
}
public boolean isOpenStdin() {
return openStdin;
}
public boolean isStdinOnce() {
return stdinOnce;
}
public List<String> getEnv() {
return env;
}
public List<String> getCmd() {
return cmd;
}
public List<String> getDns() {
return dns;
}
public String getImageId() {
return imageId;
}
public Map<String, ?> getVolumes() {
return volumes;
}
public String getVolumesFrom() {
return volumesFrom;
}
public String getWorkingDir() {
return workingDir;
}
public String getEntrypoint() {
return entrypoint;
}
public boolean isNetworkDisabled() {
return networkDisabled;
}
public List<String> getOnBuild() {
return onBuild;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Config that = (Config) o;
return Objects.equal(this.hostname, that.hostname) &&
Objects.equal(this.domainName, that.domainName) &&
Objects.equal(this.user, that.user) &&
Objects.equal(this.memory, that.memory) &&
Objects.equal(this.memorySwap, that.memorySwap) &&
Objects.equal(this.cpuShares, that.cpuShares) &&
Objects.equal(this.attachStdin, that.attachStdin) &&
Objects.equal(this.attachStdout, that.attachStdout) &&
Objects.equal(this.attachStderr, that.attachStderr) &&
Objects.equal(this.exposedPorts, that.exposedPorts) &&
Objects.equal(this.tty, that.tty) &&
Objects.equal(this.openStdin, that.openStdin) &&
Objects.equal(this.stdinOnce, that.stdinOnce) &&
Objects.equal(this.env, that.env) &&
Objects.equal(this.cmd, that.cmd) &&
Objects.equal(this.dns, that.dns) &&
Objects.equal(this.imageId, that.imageId) &&
Objects.equal(this.volumes, that.volumes) &&
Objects.equal(this.volumesFrom, that.volumesFrom) &&
Objects.equal(this.workingDir, that.workingDir) &&
Objects.equal(this.entrypoint, that.entrypoint) &&
Objects.equal(this.onBuild, that.onBuild);
}
@Override
public int hashCode() {
return Objects.hashCode(hostname, domainName, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
attachStderr, exposedPorts, tty, openStdin, stdinOnce, env, cmd, dns, imageId, volumes,
volumesFrom, workingDir, entrypoint, networkDisabled, onBuild);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("hostname", hostname)
.add("domainName", domainName)
.add("user", user)
.add("memory", memory)
.add("memorySwap", memorySwap)
.add("cpuShares", cpuShares)
.add("attachStdin", attachStdin)
.add("attachStdout", attachStdout)
.add("attachStderr", attachStderr)
.add("exposedPorts", exposedPorts)
.add("tty", tty)
.add("openStdin", openStdin)
.add("stdinOnce", stdinOnce)
.add("env", env)
.add("cmd", cmd)
.add("dns", dns)
.add("imageId", imageId)
.add("volumes", volumes)
.add("volumesFrom", volumesFrom)
.add("workingDir", workingDir)
.add("entrypoint", entrypoint)
.add("networkDisabled", networkDisabled)
.add("onBuild", onBuild)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromConfig(this);
}
public static final class Builder {
private String hostname;
private String domainName;
private String user;
private int memory;
private int memorySwap;
private int cpuShares;
private boolean attachStdin;
private boolean attachStdout;
private boolean attachStderr;
private Map<String, ?> exposedPorts = ImmutableMap.of();
private boolean tty;
private boolean openStdin;
private boolean stdinOnce;
private List<String> env = ImmutableList.of();
private List<String> cmd = ImmutableList.of();
private List<String> dns = ImmutableList.of();
private String imageId;
private Map<String, ?> volumes = ImmutableMap.of();
private String volumesFrom;
private String workingDir;
private String entrypoint;
private boolean networkDisabled;
private List<String> onBuild = ImmutableList.of();
public Builder hostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder domainName(String domainName) {
this.domainName = domainName;
return this;
}
public Builder user(String user) {
this.user = user;
return this;
}
public Builder memory(int memory) {
this.memory = memory;
return this;
}
public Builder memorySwap(int memorySwap) {
this.memorySwap = memorySwap;
return this;
}
public Builder cpuShares(int cpuShares) {
this.cpuShares = cpuShares;
return this;
}
public Builder attachStdin(boolean attachStdin) {
this.attachStdin = attachStdin;
return this;
}
public Builder attachStdout(boolean attachStdout) {
this.attachStdout = attachStdout;
return this;
}
public Builder attachStderr(boolean attachStderr) {
this.attachStderr = attachStderr;
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;
}
public Builder openStdin(boolean openStdin) {
this.openStdin = openStdin;
return this;
}
public Builder stdinOnce(boolean stdinOnce) {
this.stdinOnce = stdinOnce;
return this;
}
public Builder env(List<String> env) {
this.env = env;
return this;
}
public Builder cmd(List<String> cmd) {
this.cmd = ImmutableList.copyOf(checkNotNull(cmd, "cmd"));
return this;
}
public Builder dns(List<String> dns) {
this.dns = ImmutableList.copyOf(checkNotNull(dns, "dns"));
return this;
}
public Builder imageId(String imageId) {
this.imageId = imageId;
return this;
}
public Builder volumes(Map<String, ?> volumes) {
this.volumes = ImmutableMap.copyOf(checkNotNull(volumes, "volumes"));
return this;
}
public Builder volumesFrom(String volumesFrom) {
this.volumesFrom = volumesFrom;
return this;
}
public Builder workingDir(String workingDir) {
this.workingDir = workingDir;
return this;
}
public Builder entrypoint(String entrypoint) {
this.entrypoint = entrypoint;
return this;
}
public Builder networkDisabled(boolean networkDisabled) {
this.networkDisabled = networkDisabled;
return this;
}
public Builder onBuild(List<String> onBuild) {
this.onBuild = ImmutableList.copyOf(checkNotNull(onBuild, "onBuild"));
return this;
}
public Config build() {
return new Config(hostname, domainName, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
attachStderr, exposedPorts, tty, openStdin, stdinOnce, env, cmd, dns, imageId, volumes,
volumesFrom, workingDir, entrypoint, networkDisabled, onBuild);
}
public Builder fromConfig(Config in) {
return this
.hostname(in.getHostname())
.domainName(in.getDomainName())
.user(in.getUser())
.memory(in.getMemory())
.memorySwap(in.getMemorySwap())
.cpuShares(in.getCpuShares())
.attachStdin(in.isAttachStdin())
.attachStdout(in.isAttachStdout())
.attachStderr(in.isAttachStderr())
.exposedPorts(in.getExposedPorts())
.tty(in.isTty())
.openStdin(in.isOpenStdin())
.stdinOnce(in.isStdinOnce())
.env(in.getEnv())
.cmd(in.getCmd())
.dns(in.getDns())
.imageId(in.getImageId())
.volumes(in.getVolumes())
.volumesFrom(in.getVolumesFrom())
.workingDir(in.getWorkingDir())
.entrypoint(in.getEntrypoint())
.networkDisabled(in.isNetworkDisabled())
.onBuild(in.getOnBuild());
}
}
}

View File

@ -0,0 +1,389 @@
/*
* 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 com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.SerializedName;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
public class Container {
@SerializedName("Id")
private final String id;
@SerializedName("Name")
private final String name;
@SerializedName("Created")
private final String created;
@SerializedName("Path")
private final String path;
@SerializedName("Args")
private final String[] args;
@SerializedName("Config")
private final Config containerConfig;
@SerializedName("State")
private final State state;
@SerializedName("Image")
private final String image;
@SerializedName("NetworkSettings")
private final NetworkSettings networkSettings;
@SerializedName("ResolvConfPath")
private final String resolvConfPath;
@SerializedName("Driver")
private final String driver;
@SerializedName("ExecDriver")
private final String execDriver;
@SerializedName("Volumes")
private final Map<String, String> volumes;
@SerializedName("VolumesRW")
private final Map<String, Boolean> volumesRW;
@SerializedName("Command")
private final String command;
@SerializedName("Status")
private final String status;
@SerializedName("HostConfig")
private final HostConfig hostConfig;
@SerializedName("Ports")
private final List<Port> ports;
@SerializedName("HostnamePath")
private final String hostnamePath;
@ConstructorProperties({ "Id", "Name", "Created", "Path", "Args", "Config", "State", "Image", "NetworkSettings",
"ResolvConfPath", "Driver", "ExecDriver", "Volumes", "VolumesRW", "Command", "Status", "HostConfig",
"Ports", "HostnamePath" })
protected Container(String id, @Nullable String name, @Nullable String created, @Nullable String path, @Nullable String[] args,
@Nullable Config containerConfig, @Nullable State state, @Nullable String image, @Nullable NetworkSettings networkSettings,
@Nullable String resolvConfPath, @Nullable String driver, @Nullable String execDriver, @Nullable Map<String, String> volumes,
@Nullable Map<String, Boolean> volumesRW, @Nullable String command, @Nullable String status,
@Nullable HostConfig hostConfig, @Nullable List<Port> ports, @Nullable String hostnamePath) {
this.id = checkNotNull(id, "id");
this.name = name;
this.created = created;
this.path = path;
this.args = args;
this.containerConfig = containerConfig;
this.state = state;
this.image = image;
this.networkSettings = networkSettings;
this.resolvConfPath = resolvConfPath;
this.driver = driver;
this.execDriver = execDriver;
this.volumes = volumes != null ? ImmutableMap.copyOf(volumes) : ImmutableMap.<String, String>of();
this.volumesRW = volumesRW != null ? ImmutableMap.copyOf(volumesRW) : ImmutableMap.<String, Boolean>of();
this.command = command;
this.status = status;
this.hostConfig = hostConfig;
this.ports = ports != null ? ImmutableList.copyOf(ports) : ImmutableList.<Port>of();
this.hostnamePath = hostnamePath;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getCreated() {
return created;
}
public String getPath() {
return path;
}
public String[] getArgs() {
return args;
}
public Config getContainerConfig() {
return containerConfig;
}
public State getState() {
return state;
}
public String getImage() {
return image;
}
public NetworkSettings getNetworkSettings() {
return networkSettings;
}
public String getResolvConfPath() {
return resolvConfPath;
}
public String getDriver() {
return driver;
}
public String getExecDriver() {
return execDriver;
}
public Map<String, String> getVolumes() {
return volumes;
}
public Map<String, Boolean> getvolumesRW() {
return volumesRW;
}
public String getCommand() {
return command;
}
public String getStatus() {
return status;
}
public HostConfig getHostConfig() {
return hostConfig;
}
public List<Port> getPorts() {
return ports;
}
public String getHostnamePath() {
return hostnamePath;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Container that = (Container) o;
return Objects.equal(this.id, that.id) &&
Objects.equal(this.name, that.name) &&
Objects.equal(this.created, that.created) &&
Objects.equal(this.path, that.path) &&
Objects.equal(this.args, that.args) &&
Objects.equal(this.containerConfig, that.containerConfig) &&
Objects.equal(this.state, that.state) &&
Objects.equal(this.image, that.image) &&
Objects.equal(this.networkSettings, that.networkSettings) &&
Objects.equal(this.resolvConfPath, that.resolvConfPath) &&
Objects.equal(this.driver, that.driver) &&
Objects.equal(this.execDriver, that.execDriver) &&
Objects.equal(this.volumes, that.volumes) &&
Objects.equal(this.volumesRW, that.volumesRW) &&
Objects.equal(this.command, that.command) &&
Objects.equal(this.status, that.status) &&
Objects.equal(this.hostConfig, that.hostConfig) &&
Objects.equal(this.ports, that.ports) &&
Objects.equal(this.hostnamePath, that.hostnamePath);
}
@Override
public int hashCode() {
return Objects.hashCode(id, name, created, path, args, containerConfig, state, image, networkSettings, resolvConfPath,
driver, execDriver, volumes, volumesRW, command, status, hostConfig, ports, hostnamePath);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("id", id)
.add("name", name)
.add("created", created)
.add("path", path)
.add("args", args)
.add("containerConfig", containerConfig)
.add("state", state)
.add("image", image)
.add("networkSettings", networkSettings)
.add("resolvConfPath", resolvConfPath)
.add("driver", driver)
.add("execDriver", execDriver)
.add("volumes", volumes)
.add("volumesRW", volumesRW)
.add("command", command)
.add("status", status)
.add("hostConfig", hostConfig)
.add("ports", ports)
.add("hostnamePath", hostnamePath)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromContainer(this);
}
public static final class Builder {
private String id;
private String name;
private String created;
private String path;
private String[] args;
private Config containerConfig;
private State state;
private String image;
private NetworkSettings networkSettings;
private String resolvConfPath;
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;
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) {
this.created = created;
return this;
}
public Builder path(String path) {
this.path = path;
return this;
}
public Builder args(String[] args) {
this.args = args;
return this;
}
public Builder containerConfig(Config containerConfig) {
this.containerConfig = containerConfig;
return this;
}
public Builder state(State state) {
this.state = state;
return this;
}
public Builder image(String imageName) {
this.image = imageName;
return this;
}
public Builder networkSettings(NetworkSettings networkSettings) {
this.networkSettings = networkSettings;
return this;
}
public Builder resolvConfPath(String resolvConfPath) {
this.resolvConfPath = resolvConfPath;
return this;
}
public Builder driver(String driver) {
this.driver = driver;
return this;
}
public Builder execDriver(String execDriver) {
this.execDriver = execDriver;
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;
}
public Builder command(String command) {
this.command = command;
return this;
}
public Builder status(String status) {
this.status = status;
return this;
}
public Builder hostConfig(HostConfig hostConfig) {
this.hostConfig = hostConfig;
return this;
}
public Builder ports(List<Port> ports) {
this.ports = ports;
return this;
}
public Builder hostnamePath(String hostnamePath) {
this.hostnamePath = hostnamePath;
return this;
}
public Container build() {
return new Container(id, name, created, path, args, containerConfig, state, image, networkSettings, resolvConfPath,
driver, execDriver, volumes, volumesRW, command, status, hostConfig, ports, hostnamePath);
}
public Builder fromContainer(Container in) {
return this
.id(in.getId())
.name(in.getName())
.created(in.getCreated())
.path(in.getPath())
.args(in.getArgs())
.containerConfig(in.getContainerConfig())
.state(in.getState())
.image(in.getImage())
.networkSettings(in.getNetworkSettings())
.resolvConfPath(in.getResolvConfPath())
.driver(in.getDriver())
.execDriver(in.getExecDriver())
.volumes(in.getVolumes())
.volumesRW(in.getvolumesRW())
.command(in.getCommand())
.status(in.getStatus())
.hostConfig(in.getHostConfig())
.ports(in.getPorts())
.hostnamePath(in.getHostnamePath());
}
}
}

View File

@ -0,0 +1,106 @@
/*
* 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 com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.gson.annotations.SerializedName;
public class ExposedPorts {
@SerializedName("PortAndProtocol")
private final String portAndProtocol;
@SerializedName("HostPorts")
private final Set<String> hostPorts;
@ConstructorProperties({ "PortAndProtocol", "HostPorts" })
protected ExposedPorts(String portAndProtocol, @Nullable Set<String> hostPorts) {
this.portAndProtocol = checkNotNull(portAndProtocol, "portAndProtocol");
this.hostPorts = hostPorts != null ? ImmutableSet.copyOf(hostPorts) : ImmutableSet.<String> of();
}
public String getPortAndProtocol() {
return portAndProtocol;
}
public Set<String> getHostPorts() {
return hostPorts;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExposedPorts that = (ExposedPorts) o;
return Objects.equal(this.portAndProtocol, that.portAndProtocol) &&
Objects.equal(this.hostPorts, that.hostPorts);
}
@Override
public int hashCode() {
return Objects.hashCode(portAndProtocol, hostPorts);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("portAndProtocol", portAndProtocol)
.add("hostPorts", hostPorts)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromExposedPorts(this);
}
public static final class Builder {
private String portAndProtocol;
private Set<String> hostPorts = ImmutableSet.of();
public Builder portAndProtocol(String portAndProtocol) {
this.portAndProtocol = portAndProtocol;
return this;
}
public Builder hostPorts(Set<String> hostPorts) {
this.hostPorts = ImmutableSet.copyOf(checkNotNull(hostPorts, "hostPorts"));
return this;
}
public ExposedPorts build() {
return new ExposedPorts(portAndProtocol, hostPorts);
}
public Builder fromExposedPorts(ExposedPorts in) {
return this.portAndProtocol(in.getPortAndProtocol())
.hostPorts(in.getHostPorts());
}
}
}

View File

@ -0,0 +1,242 @@
/*
* 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 com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
public class HostConfig {
@SerializedName("ContainerIDFile")
private final String containerIDFile;
@SerializedName("Binds")
private final List<String> binds;
@SerializedName("LxcConf")
private final Map<String, String> lxcConf;
@SerializedName("Privileged")
private final boolean privileged;
@SerializedName("Dns")
private final String dns;
@SerializedName("DnsSearch")
private final String dnsSearch;
@SerializedName("PortBindings")
private final Map<String, List<Map<String, String>>> portBindings;
@SerializedName("Links")
private final List<String> links;
@SerializedName("PublishAllPorts")
private final boolean publishAllPorts;
@SerializedName("VolumesFrom")
private final List<String> volumesFrom;
@ConstructorProperties({ "ContainerIDFile", "Binds", "LxcConf", "Privileged", "Dns", "DnsSearch", "PortBindings",
"Links", "PublishAllPorts", "VolumesFrom" })
protected HostConfig(@Nullable String containerIDFile, @Nullable List<String> binds,
Map<String, String> lxcConf, boolean privileged, @Nullable String dns,
@Nullable String dnsSearch, @Nullable Map<String, List<Map<String, String>>> portBindings,
@Nullable List<String> links, boolean publishAllPorts, @Nullable List<String> volumesFrom) {
this.containerIDFile = containerIDFile;
this.binds = binds != null ? ImmutableList.copyOf(binds) : ImmutableList.<String> of();
this.lxcConf = lxcConf != null ? ImmutableMap.copyOf(lxcConf) : ImmutableMap.<String, String> of();
this.privileged = checkNotNull(privileged, "privileged");
this.dns = dns;
this.dnsSearch = dnsSearch;
this.portBindings = portBindings != null ? ImmutableMap.copyOf(portBindings) : ImmutableMap.<String, List<Map<String, String>>> of();
this.links = links != null ? ImmutableList.copyOf(links) : ImmutableList.<String> of();
this.publishAllPorts = checkNotNull(publishAllPorts, "publishAllPorts");
this.volumesFrom = volumesFrom != null ? ImmutableList.copyOf(volumesFrom) : ImmutableList.<String> of();
}
public String getContainerIDFile() {
return containerIDFile;
}
public List<String> getBinds() {
return binds;
}
public Map<String, String> getLxcConf() {
return lxcConf;
}
public boolean isPrivileged() {
return privileged;
}
public String getDns() { return dns; }
public String getDnsSearch() { return dnsSearch; }
public Map<String, List<Map<String, String>>> getPortBindings() {
return portBindings;
}
@Nullable
public List<String> getLinks() {
return links;
}
public boolean isPublishAllPorts() {
return publishAllPorts;
}
public List<String> getVolumesFrom() {
return volumesFrom;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HostConfig that = (HostConfig) o;
return Objects.equal(this.containerIDFile, that.containerIDFile) &&
Objects.equal(this.binds, that.binds) &&
Objects.equal(this.lxcConf, that.lxcConf) &&
Objects.equal(this.privileged, that.privileged) &&
Objects.equal(this.dns, that.dns) &&
Objects.equal(this.dnsSearch, that.dnsSearch) &&
Objects.equal(this.portBindings, that.portBindings) &&
Objects.equal(this.links, that.links) &&
Objects.equal(this.publishAllPorts, that.publishAllPorts) &&
Objects.equal(this.volumesFrom, that.volumesFrom);
}
@Override
public int hashCode() {
return Objects.hashCode(containerIDFile, binds, lxcConf, privileged, dns, dnsSearch, portBindings, links,
publishAllPorts, volumesFrom);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("containerIDFile", containerIDFile)
.add("binds", binds)
.add("lxcConf", lxcConf)
.add("privileged", privileged)
.add("dns", dns)
.add("dnsSearch", dnsSearch)
.add("portBindings", portBindings)
.add("links", links)
.add("publishAllPorts", publishAllPorts)
.add("volumesFrom", volumesFrom)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromHostConfig(this);
}
public static final class Builder {
private String containerIDFile;
private List<String> binds = Lists.newArrayList();
private Map<String, String> lxcConf = Maps.newLinkedHashMap();
private boolean privileged;
private String dns;
private String dnsSearch;
private Map<String, List<Map<String, String>>> portBindings = Maps.newLinkedHashMap();
private List<String> links = Lists.newArrayList();
private boolean publishAllPorts;
private List<String> volumesFrom = Lists.newArrayList();
public Builder containerIDFile(String containerIDFile) {
this.containerIDFile = containerIDFile;
return this;
}
public Builder binds(List<String> binds) {
this.binds.addAll(checkNotNull(binds, "binds"));
return this;
}
public Builder lxcConf(Map<String, String> lxcConf) {
this.lxcConf.putAll(checkNotNull(lxcConf, "lxcConf"));
return this;
}
public Builder privileged(boolean privileged) {
this.privileged = privileged;
return this;
}
public Builder dns(String dns) {
this.dns = dns;
return this;
}
public Builder dnsSearch(String dnsSearch) {
this.dnsSearch = dnsSearch;
return this;
}
public Builder links(List<String> links) {
this.links.addAll(checkNotNull(links, "links"));
return this;
}
public Builder portBindings(Map<String, List<Map<String, String>>> portBindings) {
this.portBindings.putAll(portBindings);
return this;
}
public Builder publishAllPorts(boolean publishAllPorts) {
this.publishAllPorts = publishAllPorts;
return this;
}
public Builder volumesFrom(List<String> volumesFrom) {
this.volumesFrom.addAll(checkNotNull(volumesFrom, "volumesFrom"));
return this;
}
public HostConfig build() {
return new HostConfig(containerIDFile, binds, lxcConf, privileged, dns, dnsSearch, portBindings, links,
publishAllPorts, volumesFrom);
}
public Builder fromHostConfig(HostConfig in) {
return this
.containerIDFile(in.getContainerIDFile())
.binds(in.getBinds())
.lxcConf(in.getLxcConf())
.privileged(in.isPrivileged())
.dns(in.getDns())
.dnsSearch(in.getDnsSearch())
.links(in.getLinks())
.portBindings(in.getPortBindings())
.publishAllPorts(in.isPublishAllPorts())
.volumesFrom(in.getVolumesFrom());
}
}
}

View File

@ -0,0 +1,239 @@
/*
* 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 com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.gson.annotations.SerializedName;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
public class Image {
@SerializedName("Id")
private final String id;
@SerializedName("Parent")
private final String parent;
@SerializedName("Created")
private final String created;
@SerializedName("Container")
private final String container;
@SerializedName("DockerVersion")
private final String dockerVersion;
@SerializedName("Architecture")
private final String architecture;
@SerializedName("Os")
private final String os;
@SerializedName("Size")
private final long size;
@SerializedName("VirtualSize")
private final long virtualSize;
@SerializedName("RepoTags")
private final List<String> repoTags;
@ConstructorProperties({ "Id", "Parent", "Created", "Container", "DockerVersion", "Architecture", "Os", "Size",
"VirtualSize", "RepoTags", "Architecture" })
protected Image(String id, @Nullable String parent, @Nullable String created, @Nullable String container,
@Nullable String dockerVersion, @Nullable String architecture, @Nullable String os, long size,
@Nullable long virtualSize, @Nullable List<String> repoTags) {
this.id = checkNotNull(id, "id");
this.parent = parent;
this.created = created;
this.container = container;
this.dockerVersion = dockerVersion;
this.architecture = architecture;
this.os = os;
this.size = size;
this.virtualSize = virtualSize;
this.repoTags = repoTags != null ? ImmutableList.copyOf(repoTags) : ImmutableList.<String> of();
}
public String getId() {
return id;
}
public String getParent() {
return parent;
}
public String getCreated() {
return created;
}
public String getContainer() {
return container;
}
public String getDockerVersion() {
return dockerVersion;
}
public String getArchitecture() {
return architecture;
}
public String getOs() {
return os;
}
public long getSize() {
return size;
}
public long getVirtualSize() {
return virtualSize;
}
public List<String> getRepoTags() {
return repoTags;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Image that = (Image) o;
return Objects.equal(this.id, that.id) &&
Objects.equal(this.parent, that.parent) &&
Objects.equal(this.created, that.created) &&
Objects.equal(this.container, that.container) &&
Objects.equal(this.dockerVersion, that.dockerVersion) &&
Objects.equal(this.architecture, that.architecture) &&
Objects.equal(this.os, that.os) &&
Objects.equal(this.size, that.size) &&
Objects.equal(this.virtualSize, that.virtualSize);
}
@Override
public int hashCode() {
return Objects.hashCode(id, parent, created, container, dockerVersion, architecture, os, size,
virtualSize);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("id", id)
.add("parent", parent)
.add("created", created)
.add("container", container)
.add("dockerVersion", dockerVersion)
.add("architecture", architecture)
.add("os", os)
.add("size", size)
.add("virtualSize", virtualSize)
.add("repoTags", repoTags)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromImage(this);
}
public static final class Builder {
private String id;
private String parent;
private String created;
private String container;
private String dockerVersion;
private String architecture;
private String os;
private long size;
private long virtualSize;
private List<String> repoTags = ImmutableList.of();
public Builder id(String id) {
this.id = id;
return this;
}
public Builder parent(String parent) {
this.parent = parent;
return this;
}
public Builder created(String created) {
this.created = created;
return this;
}
public Builder container(String container) {
this.container = container;
return this;
}
public Builder dockerVersion(String dockerVersion) {
this.dockerVersion = dockerVersion;
return this;
}
public Builder architecture(String architecture) {
this.architecture = architecture;
return this;
}
public Builder os(String os) {
this.os = os;
return this;
}
public Builder size(long size) {
this.size = size;
return this;
}
public Builder virtualSize(long virtualSize) {
this.virtualSize = virtualSize;
return this;
}
public Builder repoTags(List<String> repoTags) {
this.repoTags = ImmutableList.copyOf(checkNotNull(repoTags, "repoTags"));
return this;
}
public Image build() {
return new Image(id, parent, created, container, dockerVersion, architecture, os, size,
virtualSize, repoTags);
}
public Builder fromImage(Image in) {
return this
.id(in.getId())
.parent(in.getParent())
.created(in.getCreated())
.container(in.getContainer())
.dockerVersion(in.getDockerVersion())
.architecture(in.getArchitecture())
.os(in.getOs())
.size(in.getSize())
.virtualSize(in.getVirtualSize());
//DO NOT add .repoTags(in.getRepoTags());
}
}
}

View File

@ -0,0 +1,175 @@
/*
* 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 com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.SerializedName;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
public class NetworkSettings {
@SerializedName("IPAddress")
private final String ipAddress;
@SerializedName("IPPrefixLen")
private final int ipPrefixLen;
@SerializedName("Gateway")
private final String gateway;
@SerializedName("Bridge")
private final String bridge;
@SerializedName("PortMapping")
private final String portMapping;
@SerializedName("Ports")
private final Map<String, List<Map<String, String>>> ports;
@ConstructorProperties({ "IPAddress", "IPPrefixLen", "Gateway", "Bridge", "PortMapping", "Ports" })
protected NetworkSettings(String ipAddress, int ipPrefixLen, String gateway, String bridge,
@Nullable String portMapping, @Nullable Map<String, List<Map<String, String>>> ports) {
this.ipAddress = checkNotNull(ipAddress, "ipAddress");
this.ipPrefixLen = checkNotNull(ipPrefixLen, "ipPrefixLen");
this.gateway = checkNotNull(gateway, "gateway");
this.bridge = checkNotNull(bridge, "bridge");
this.portMapping = portMapping;
this.ports = ports != null ? ImmutableMap.copyOf(ports) : ImmutableMap.<String, List<Map<String, String>>> of();
}
public String getIpAddress() {
return ipAddress;
}
public int getIpPrefixLen() {
return ipPrefixLen;
}
public String getGateway() {
return gateway;
}
public String getBridge() {
return bridge;
}
public String getPortMapping() {
return portMapping;
}
public Map<String, List<Map<String, String>>> getPorts() {
return ports;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NetworkSettings that = (NetworkSettings) o;
return Objects.equal(this.ipAddress, that.ipAddress) &&
Objects.equal(this.ipPrefixLen, that.ipPrefixLen) &&
Objects.equal(this.gateway, that.gateway) &&
Objects.equal(this.bridge, that.bridge) &&
Objects.equal(this.portMapping, that.portMapping) &&
Objects.equal(this.ports, that.ports);
}
@Override
public int hashCode() {
return Objects.hashCode(ipAddress, ipPrefixLen, gateway, bridge, portMapping, ports);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("ipAddress", ipAddress)
.add("ipPrefixLen", ipPrefixLen)
.add("gateway", gateway)
.add("bridge", bridge)
.add("portMapping", portMapping)
.add("ports", ports)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromNetworkSettings(this);
}
public static final class Builder {
private String ipAddress;
private int ipPrefixLen;
private String gateway;
private String bridge;
private String portMapping;
private Map<String, List<Map<String, String>>> ports = ImmutableMap.of();
public Builder ipAddress(String ipAddress) {
this.ipAddress = ipAddress;
return this;
}
public Builder ipPrefixLen(int ipPrefixLen) {
this.ipPrefixLen = ipPrefixLen;
return this;
}
public Builder gateway(String gateway) {
this.gateway = gateway;
return this;
}
public Builder bridge(String bridge) {
this.bridge = bridge;
return this;
}
public Builder portMapping(String portMapping) {
this.portMapping = portMapping;
return this;
}
public Builder ports(Map<String, List<Map<String, String>>> ports) {
this.ports = ImmutableMap.copyOf(checkNotNull(ports, "ports"));
return this;
}
public NetworkSettings build() {
return new NetworkSettings(ipAddress, ipPrefixLen, gateway, bridge, portMapping, ports);
}
public Builder fromNetworkSettings(NetworkSettings in) {
return this
.ipAddress(in.getIpAddress())
.ipPrefixLen(in.getIpPrefixLen())
.gateway(in.getGateway())
.bridge(in.getBridge())
.portMapping(in.getPortMapping())
.ports(in.getPorts());
}
}
}

View File

@ -0,0 +1,88 @@
/*
* 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 com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
import java.beans.ConstructorProperties;
import static com.google.common.base.Preconditions.checkNotNull;
public class Port {
@SerializedName("PrivatePort")
private final int privatePort;
@SerializedName("PublicPort")
private final int publicPort;
@SerializedName("Type")
private final String type;
@SerializedName("IP")
private final String ip;
@ConstructorProperties({ "PrivatePort", "PublicPort", "Type", "IP" })
protected Port(int privatePort, int publicPort, String type, String ip) {
this.privatePort = checkNotNull(privatePort, "privatePort");
this.publicPort = checkNotNull(publicPort, "publicPort");
this.type = checkNotNull(type, "type");
this.ip = checkNotNull(ip, "ip");
}
public int getPrivatePort() {
return privatePort;
}
public int getPublicPort() {
return publicPort;
}
public String getType() {
return type;
}
public String getIp() {
return ip;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Port that = (Port) o;
return Objects.equal(this.privatePort, that.privatePort) &&
Objects.equal(this.publicPort, that.publicPort) &&
Objects.equal(this.type, that.type) &&
Objects.equal(this.ip, that.ip);
}
@Override
public int hashCode() {
return Objects.hashCode(privatePort, publicPort, type, ip);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("privatePort", privatePort)
.add("publicPort", publicPort)
.add("type", type)
.add("ip", ip)
.toString();
}
}

View File

@ -0,0 +1,166 @@
/*
* 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 com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
public class State {
@SerializedName("Pid")
private final int pid;
@SerializedName("Running")
private final boolean running;
@SerializedName("ExitCode")
private final int exitCode;
@SerializedName("StartedAt")
private final String startedAt;
@SerializedName("FinishedAt")
private final String finishedAt;
@SerializedName("Ghost")
private final boolean ghost;
@ConstructorProperties({ "Pid", "Running", "ExitCode", "StartedAt", "FinishedAt", "Ghost" })
protected State(int pid, boolean running, int exitCode, String startedAt, String finishedAt, boolean ghost) {
this.pid = checkNotNull(pid, "pid");
this.running = checkNotNull(running, "running");
this.exitCode = checkNotNull(exitCode, "exitCode");
this.startedAt = checkNotNull(startedAt, "startedAt");
this.finishedAt = checkNotNull(finishedAt, "finishedAt");
this.ghost = checkNotNull(ghost, "ghost");
}
public int getPid() {
return pid;
}
public boolean isRunning() {
return running;
}
public int getExitCode() {
return exitCode;
}
public String getStartedAt() {
return startedAt;
}
public String getFinishedAt() {
return finishedAt;
}
public boolean isGhost() {
return ghost;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
State that = (State) o;
return Objects.equal(this.pid, that.pid) &&
Objects.equal(this.running, that.running) &&
Objects.equal(this.exitCode, that.exitCode) &&
Objects.equal(this.startedAt, that.startedAt) &&
Objects.equal(this.finishedAt, that.finishedAt) &&
Objects.equal(this.ghost, that.ghost);
}
@Override
public int hashCode() {
return Objects.hashCode(pid, running, exitCode, startedAt, finishedAt, ghost);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("pid", pid)
.add("running", running)
.add("exitCode", exitCode)
.add("startedAt", startedAt)
.add("finishedAt", finishedAt)
.add("ghost", ghost)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromState(this);
}
public static final class Builder {
private int pid;
private boolean running;
private int exitCode;
private String startedAt;
private String finishedAt;
private boolean ghost;
public Builder pid(int pid) {
this.pid = pid;
return this;
}
public Builder running(boolean running) {
this.running = running;
return this;
}
public Builder exitCode(int exitCode) {
this.exitCode = exitCode;
return this;
}
public Builder startedAt(String startedAt) {
this.startedAt = startedAt;
return this;
}
public Builder finishedAt(String finishedAt) {
this.finishedAt = finishedAt;
return this;
}
public Builder ghost(boolean ghost) {
this.ghost = ghost;
return this;
}
public State build() {
return new State(pid, running, exitCode, startedAt, finishedAt, ghost);
}
public Builder fromState(State in) {
return this
.pid(in.getPid())
.running(in.isRunning())
.exitCode(in.getExitCode())
.startedAt(in.getStartedAt())
.finishedAt(in.getFinishedAt())
.ghost(in.isGhost());
}
}
}

View File

@ -0,0 +1,166 @@
/*
* 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 com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
public class Version {
@SerializedName("Arch")
private final String arch;
@SerializedName("GitCommit")
private final String gitCommit;
@SerializedName("GoVersion")
private final String goVersion;
@SerializedName("KernelVersion")
private final String kernelVersion;
@SerializedName("Os")
private final String os;
@SerializedName("Version")
private final String version;
@ConstructorProperties({ "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
protected Version(String arch, String gitCommit, String goVersion, String kernelVersion, String os, String version) {
this.arch = checkNotNull(arch, "arch");
this.gitCommit = checkNotNull(gitCommit, "gitCommit");
this.goVersion = checkNotNull(goVersion, "goVersion");
this.kernelVersion = checkNotNull(kernelVersion, "kernelVersion");
this.os = checkNotNull(os, "os");
this.version = checkNotNull(version, "version");
}
public String getArch() {
return arch;
}
public String getGitCommit() {
return gitCommit;
}
public String getGoVersion() {
return goVersion;
}
public String getKernelVersion() {
return kernelVersion;
}
public String getOs() {
return os;
}
public String getVersion() {
return version;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Version that = (Version) o;
return Objects.equal(this.arch, that.arch) &&
Objects.equal(this.gitCommit, that.gitCommit) &&
Objects.equal(this.goVersion, that.goVersion) &&
Objects.equal(this.kernelVersion, that.kernelVersion) &&
Objects.equal(this.os, that.os) &&
Objects.equal(this.version, that.version);
}
@Override
public int hashCode() {
return Objects.hashCode(arch, gitCommit, goVersion, kernelVersion, os, version);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("arch", arch)
.add("gitCommit", gitCommit)
.add("goVersion", goVersion)
.add("kernelVersion", kernelVersion)
.add("os", os)
.add("version", version)
.toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromVersion(this);
}
public static final class Builder {
private String arch;
private String gitCommit;
private String goVersion;
private String kernelVersion;
private String os;
private String version;
public Builder arch(String arch) {
this.arch = arch;
return this;
}
public Builder gitCommit(String gitCommit) {
this.gitCommit = gitCommit;
return this;
}
public Builder goVersion(String goVersion) {
this.goVersion = goVersion;
return this;
}
public Builder kernelVersion(String kernelVersion) {
this.kernelVersion = kernelVersion;
return this;
}
public Builder os(String os) {
this.os = os;
return this;
}
public Builder version(String version) {
this.version = version;
return this;
}
public Version build() {
return new Version(arch, gitCommit, goVersion, kernelVersion, os, version);
}
public Builder fromVersion(Version in) {
return this
.arch(in.getArch())
.gitCommit(in.getGitCommit())
.goVersion(in.getGoVersion())
.kernelVersion(in.getKernelVersion())
.os(in.getOs())
.version(in.getVersion());
}
}
}

View File

@ -0,0 +1,272 @@
/*
* 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.File;
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.binders.BindInputStreamToRequest;
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 containers 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 operations 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 containers 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 containers changes
*
* @param options the commits 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);
/**
* Build an image from Dockerfile via stdin
*
* @param dockerFile The file to be compressed with one of the following algorithms: identity, 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(@BinderParam(BindInputStreamToRequest.class) File dockerFile, BuildOptions options);
}

View File

@ -0,0 +1,60 @@
/*
* 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.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.getLast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import com.google.common.base.Splitter;
import com.google.common.io.Files;
public class Archives {
public static File tar(File baseDir, String archivePath) throws IOException {
return tar(baseDir, new File(archivePath));
}
public static File tar(File baseDir, File tarFile) throws IOException {
// Check that the directory is a directory, and get its contents
checkArgument(baseDir.isDirectory(), "%s is not a directory", baseDir);
File[] files = baseDir.listFiles();
String token = getLast(Splitter.on("/").split(baseDir.getAbsolutePath()));
TarArchiveOutputStream tos = new TarArchiveOutputStream(new FileOutputStream(tarFile));
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
try {
for (File file : files) {
TarArchiveEntry tarEntry = new TarArchiveEntry(file);
tarEntry.setName("/" + getLast(Splitter.on(token).split(file.toString())));
tos.putArchiveEntry(tarEntry);
if (!file.isDirectory()) {
Files.asByteSource(file).copyTo(tos);
}
tos.closeArchiveEntry();
}
} finally {
tos.close();
}
return tarFile;
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.handlers;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Strings2;
import javax.annotation.Resource;
import java.io.IOException;
/**
* This will parse and set an appropriate exception on the command object.
* <p/>
* <p/>
* Errors are returned with an appropriate HTTP status code, an X-Elastic- Error header specifying
* the error type, and a text description in the HTTP body.
*/
public class DockerErrorHandler implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
String message = parseMessage(response);
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
try {
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 400:
if ((command.getCurrentRequest().getEndpoint().getPath().endsWith("/info"))
|| (message != null && message.indexOf("could not be found") != -1))
exception = new ResourceNotFoundException(message, exception);
else if (message != null && message.indexOf("currently in use") != -1)
exception = new IllegalStateException(message, exception);
else
exception = new IllegalArgumentException(message, exception);
break;
case 401:
exception = new AuthorizationException(message, exception);
break;
case 402:
exception = new IllegalStateException(message, exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
case 405:
exception = new IllegalArgumentException(message, exception);
break;
case 409:
exception = new IllegalStateException(message, exception);
break;
}
} finally {
try {
Closeables.close(response.getPayload(), true);
} catch (IOException e) {
// This code will never be reached
throw Throwables.propagate(e);
}
command.setException(exception);
}
}
public String parseMessage(HttpResponse response) {
if (response.getPayload() == null)
return null;
try {
return Strings2.toString(response.getPayload());
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
try {
response.getPayload().close();
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}
}

View File

@ -0,0 +1,71 @@
/*
* 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;
/**
* 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;
}
public BuildOptions verbose(Boolean verbose) {
this.queryParameters.put("verbose", verbose.toString());
return this;
}
public BuildOptions nocache(Boolean nocache) {
this.queryParameters.put("nocache", nocache.toString());
return this;
}
public static class Builder {
/**
* @see BuildOptions#tag
*/
public static BuildOptions tag(String tag) {
BuildOptions options = new BuildOptions();
return options.tag(tag);
}
/**
* @see BuildOptions#verbose(Boolean)
*/
public static BuildOptions verbose(Boolean verbose) {
BuildOptions options = new BuildOptions();
return options.verbose(verbose);
}
/**
* @see BuildOptions#nocache(Boolean)
*/
public static BuildOptions nocache(Boolean nocache) {
BuildOptions options = new BuildOptions();
return options.nocache(nocache);
}
}
}

View File

@ -0,0 +1,109 @@
/*
* 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;
/**
* 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;
}
public CommitOptions repository(String repository) {
this.queryParameters.put("repository", repository);
return this;
}
public CommitOptions tag(String tag) {
this.queryParameters.put("tag", tag);
return this;
}
public CommitOptions message(String message) {
this.queryParameters.put("message", message);
return this;
}
public CommitOptions author(String author) {
this.queryParameters.put("author", author);
return this;
}
public CommitOptions run(String run) {
this.queryParameters.put("run", run);
return this;
}
public static class Builder {
/**
* @see CommitOptions#containerId
*/
public static CommitOptions containerId(String containerId) {
CommitOptions options = new CommitOptions();
return options.containerId(containerId);
}
/**
* @see CommitOptions#repository
*/
public static CommitOptions repository(String repository) {
CommitOptions options = new CommitOptions();
return options.repository(repository);
}
/**
* @see CommitOptions#tag
*/
public static CommitOptions tag(String tag) {
CommitOptions options = new CommitOptions();
return options.tag(tag);
}
/**
* @see CommitOptions#message
*/
public static CommitOptions message(String message) {
CommitOptions options = new CommitOptions();
return options.message(message);
}
/**
* @see CommitOptions#author
*/
public static CommitOptions author(String author) {
CommitOptions options = new CommitOptions();
return options.author(author);
}
/**
* @see CommitOptions#run
*/
public static CommitOptions run(String run) {
CommitOptions options = new CommitOptions();
return options.run(run);
}
}
}

View File

@ -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.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;
}
public CreateImageOptions fromSrc(String fromSrc) {
this.queryParameters.put("fromSrc", fromSrc);
return this;
}
public CreateImageOptions repo(String repo) {
this.queryParameters.put("repo", repo);
return this;
}
public CreateImageOptions tag(String tag) {
this.queryParameters.put("tag", tag);
return this;
}
public CreateImageOptions registry(String registry) {
this.queryParameters.put("registry", registry);
return this;
}
public static class Builder {
/**
* @see CreateImageOptions#fromImage
*/
public static CreateImageOptions fromImage(String fromImage) {
CreateImageOptions options = new CreateImageOptions();
return options.fromImage(fromImage);
}
/**
* @see CreateImageOptions#fromSrc
*/
public static CreateImageOptions fromSrc(String fromSrc) {
CreateImageOptions options = new CreateImageOptions();
return options.fromSrc(fromSrc);
}
/**
* @see CreateImageOptions#repo
*/
public static CreateImageOptions repo(String repo) {
CreateImageOptions options = new CreateImageOptions();
return options.repo(repo);
}
/**
* @see CreateImageOptions#tag
*/
public static CreateImageOptions tag(String tag) {
CreateImageOptions options = new CreateImageOptions();
return options.tag(tag);
}
/**
* @see CreateImageOptions#registry
*/
public static CreateImageOptions registry(String registry) {
CreateImageOptions options = new CreateImageOptions();
return options.registry(registry);
}
}
}

View File

@ -0,0 +1,44 @@
/*
* 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;
/**
* 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 static class Builder {
/**
* @see DeleteImageOptions#force
*/
public static DeleteImageOptions force(Boolean force) {
DeleteImageOptions options = new DeleteImageOptions();
return options.force(force);
}
}
}

View File

@ -0,0 +1,97 @@
/*
* 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;
/**
* 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;
}
public ListContainerOptions limit(Integer limit) {
this.queryParameters.put("limit", limit.toString());
return this;
}
public ListContainerOptions since(Integer since) {
this.queryParameters.put("since", since.toString());
return this;
}
public ListContainerOptions before(Integer before) {
this.queryParameters.put("before", before.toString());
return this;
}
public ListContainerOptions size(Integer size) {
this.queryParameters.put("size", size.toString());
return this;
}
public static class Builder {
/**
* @see ListContainerOptions#all
*/
public static ListContainerOptions all(Boolean all) {
ListContainerOptions options = new ListContainerOptions();
return options.all(all);
}
/**
* @see ListContainerOptions#limit(Integer)
*/
public static ListContainerOptions limit(Integer limit) {
ListContainerOptions options = new ListContainerOptions();
return options.limit(limit);
}
/**
* @see ListContainerOptions#since(Integer)
*/
public static ListContainerOptions since(Integer since) {
ListContainerOptions options = new ListContainerOptions();
return options.since(since);
}
/**
* @see ListContainerOptions#before(Integer)
*/
public static ListContainerOptions before(Integer before) {
ListContainerOptions options = new ListContainerOptions();
return options.before(before);
}
/**
* @see ListContainerOptions#limit(Integer)
*/
public static ListContainerOptions size(Integer size) {
ListContainerOptions options = new ListContainerOptions();
return options.size(size);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* 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;
/**
* 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;
}
public static class Builder {
/**
* @see ListImageOptions#all
*/
public static ListImageOptions all(Boolean all) {
ListImageOptions options = new ListImageOptions();
return options.all(all);
}
}
}

View File

@ -0,0 +1,55 @@
/*
* 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;
/**
* 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;
}
public RemoveContainerOptions force(Boolean force) {
this.queryParameters.put("force", force.toString());
return this;
}
public static class Builder {
/**
* @see RemoveContainerOptions#verbose
*/
public static RemoveContainerOptions verbose(Boolean verbose) {
RemoveContainerOptions options = new RemoveContainerOptions();
return options.verbose(verbose);
}
/**
* @see RemoveContainerOptions#force
*/
public static RemoveContainerOptions force(Boolean force) {
RemoveContainerOptions options = new RemoveContainerOptions();
return options.force(force);
}
}
}

View File

@ -0,0 +1 @@
org.jclouds.docker.DockerApiMetadata

View File

@ -0,0 +1,47 @@
/*
* 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;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.Apis;
import org.jclouds.compute.internal.BaseComputeServiceApiMetadataTest;
import org.testng.annotations.Test;
/**
* Unit tests for the {@link DockerApiMetadata} class.
*/
@Test(groups = "unit", testName = "AbiquoApiMetadataTest")
public class DockerApiMetadataTest extends BaseComputeServiceApiMetadataTest {
public DockerApiMetadataTest() {
super(new DockerApiMetadata());
}
public void testDockerApiRegistered() {
ApiMetadata api = Apis.withId("docker");
assertNotNull(api);
assertTrue(api instanceof DockerApiMetadata);
assertEquals(api.getId(), "docker");
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.binders;
import com.google.common.io.CharStreams;
import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import static org.testng.Assert.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
@Test(groups = "unit", testName = "BindInputStreamToRequestTest")
public class BindInputStreamToRequestTest {
@Test
public void testBindInputStreamToRequest() throws IOException {
BindInputStreamToRequest binder = new BindInputStreamToRequest();
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://test").build();
request = binder.bindToRequest(request, File.createTempFile("dockerfile", ""));
String rawContent = CharStreams.toString(new InputStreamReader((FileInputStream) request.getPayload().getRawContent(), "UTF-8"));
assertTrue(rawContent.startsWith("Dockerfile"));
assertEquals(request.getPayload().getContentMetadata().getContentType(), "application/tar");
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testBindInputStreamToRequestWithObjectAsInput() throws IOException {
BindInputStreamToRequest binder = new BindInputStreamToRequest();
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://test").build();
request = binder.bindToRequest(request, new Object());
String rawContent = CharStreams.toString(new InputStreamReader((FileInputStream) request.getPayload().getRawContent(), "UTF-8"));
assertTrue(rawContent.startsWith("Dockerfile"));
assertEquals(request.getPayload().getContentMetadata().getContentType(), "application/tar");
}
@Test(expectedExceptions = NullPointerException.class)
public void testBindInputStreamToRequestWithNullInput() throws IOException {
BindInputStreamToRequest binder = new BindInputStreamToRequest();
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://test").build();
request = binder.bindToRequest(request, null);
String rawContent = CharStreams.toString(new InputStreamReader((FileInputStream) request.getPayload().getRawContent(), "UTF-8"));
assertTrue(rawContent.startsWith("Dockerfile"));
assertEquals(request.getPayload().getContentMetadata().getContentType(), "application/tar");
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.compute;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import com.google.inject.Module;
import org.jclouds.Constants;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.features.internal.Archives;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;
@Test(groups = "live")
public class BaseDockerApiLiveTest extends BaseApiLiveTest<DockerApi> {
public BaseDockerApiLiveTest() {
provider = "docker";
}
@Override
protected Iterable<Module> setupModules() {
return ImmutableSet.<Module>of(getLoggingModule(), new SshjSshClientModule());
}
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "15");
overrides.setProperty("jclouds.ssh.retry-auth", "true");
return overrides;
}
protected String consumeStream(InputStream stream, boolean swallowIOException) {
String result = null;
try {
result = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.close(stream, swallowIOException);
} catch (IOException e) {
Assert.fail();
}
return result;
}
protected Payload createPayload() throws IOException {
String folderPath = System.getProperty("user.dir") + "/docker/src/test/resources";
File parentDir = new File(folderPath + "/archive");
parentDir.mkdirs();
URL url = Resources.getResource("Dockerfile");
String content = Resources.toString(url, Charsets.UTF_8);
final File dockerfile = new File(parentDir.getAbsolutePath() + File.separator + "Dockerfile");
Files.write(content.getBytes(), dockerfile);
File archive = Archives.tar(parentDir, folderPath + "/archive/archive.tar");
FileInputStream data = new FileInputStream(archive);
Payload payload = Payloads.newInputStreamPayload(data);
payload.getContentMetadata().setContentLength(data.getChannel().size());
payload.getContentMetadata().setContentType("application/tar");
return payload;
}
}

View File

@ -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.compute;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import java.util.Properties;
import java.util.Random;
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.strategy.DockerComputeServiceAdapter;
import org.jclouds.docker.domain.Container;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Module;
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceAdapterLiveTest")
public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
private DockerComputeServiceAdapter adapter;
private TemplateBuilder templateBuilder;
private NodeAndInitialCredentials<Container> guest;
@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);
return injector.getInstance(DockerApi.class);
}
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "container-" + new Random().nextInt();
Template template = templateBuilder.smallest()
.osDescriptionMatches("jclouds/default:latest").build();
guest = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
assertEquals(guest.getNodeId(), guest.getNode().getId() + "");
}
public void testListHardwareProfiles() {
Iterable<Hardware> profiles = adapter.listHardwareProfiles();
assertFalse(Iterables.isEmpty(profiles));
for (Hardware profile : profiles) {
assertNotNull(profile);
}
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (guest != null) {
adapter.destroyNode(guest.getNode().getId() + "");
}
super.tearDown();
}
@Override
protected Iterable<Module> setupModules() {
return ImmutableSet.<Module>of(getLoggingModule(), new SshjSshClientModule());
}
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
properties.setProperty("jclouds.ssh.max-retries", "10");
return properties;
}
}

View File

@ -0,0 +1,142 @@
/*
* 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.compute;
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.sshj.config.SshjSshClientModule;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
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 {
private static final String DEFAULT_JCLOUDS_IMAGE = "jclouds/default";
private Image defaultImage;
public DockerComputeServiceLiveTest() {
provider = "docker";
}
@Override
protected Module getSshModule() {
return new SshjSshClientModule();
}
@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();
}
@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
}
@Override
protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
// Docker does not support user metadata
}
@Override
public void testCreateAndRunAService() throws Exception {
// Docker does not support blockOnPort
}
@Override
@Test(enabled = true, dependsOnMethods = { "testCompareSizes" })
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
super.testAScriptExecutionAfterBootWithBasicTemplate();
}
@Override
@Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class)
public void testSuspendResume() throws Exception {
super.testSuspendResume();
}
@Override
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testGetNodesWithDetails() throws Exception {
super.testGetNodesWithDetails();
}
@Override
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodes() throws Exception {
super.testListNodes();
}
@Override
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodesByIds() throws Exception {
super.testListNodesByIds();
}
@Override
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
public void testDestroyNodes() {
super.testDestroyNodes();
}
@Test(enabled = true, expectedExceptions = NullPointerException.class)
public void testCorrectExceptionRunningNodesNotFound() throws Exception {
super.testCorrectExceptionRunningNodesNotFound();
}
@Test(enabled = true, expectedExceptions = NullPointerException.class)
public void testCorrectAuthException() throws Exception {
// Docker does not support authentication yet
super.testCorrectAuthException();
}
}

View File

@ -0,0 +1,204 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* work for additional information regarding copyright ownership.
* The ASF licenses file to You under the Apache License, Version 2.0
* (the "License"); you may not use 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.compute.functions;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.easymock.EasyMock;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
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.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.Port;
import org.jclouds.docker.domain.State;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.providers.ProviderMetadata;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* Unit tests for the {@link org.jclouds.docker.compute.functions.ContainerToNodeMetadata} class.
*/
@Test(groups = "unit", testName = "ContainerToNodeMetadataTest")
public class ContainerToNodeMetadataTest {
private ContainerToNodeMetadata function;
private Container container;
@BeforeMethod
public void setup() {
Config containerConfig = Config.builder()
.hostname("6d35806c1bd2")
.domainName("")
.user("")
.memory(0)
.memorySwap(0)
.cpuShares(0)
.attachStdin(false)
.attachStdout(false)
.attachStderr(false)
.exposedPorts(ImmutableMap.of("22/tcp", ImmutableMap.of()))
.tty(false)
.openStdin(false)
.stdinOnce(false)
.env(null)
.cmd(ImmutableList.of("/usr/sbin/sshd", "-D"))
.imageId("jclouds/ubuntu")
.volumesFrom("")
.workingDir("")
.entrypoint(null)
.networkDisabled(false)
.build();
State state = State.builder()
.pid(3626)
.running(true)
.exitCode(0)
.startedAt("2014-03-24T20:28:37.537659054Z")
.finishedAt("0001-01-01T00:00:00Z")
.ghost(false)
.build();
container = Container.builder()
.id("6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9")
.name("/hopeful_mclean")
.created("2014-03-22T07:16:45.784120972Z")
.path("/usr/sbin/sshd")
.args(new String[] {"-D"})
.containerConfig(containerConfig)
.state(state)
.image("af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6")
.networkSettings(NetworkSettings.builder()
.ipAddress("172.17.0.2")
.ipPrefixLen(16)
.gateway("172.17.42.1")
.bridge("docker0")
.ports(ImmutableMap.<String, List<Map<String, String>>>of("22/tcp",
ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "0.0.0.0", "HostPort",
"49199"))))
.build())
.resolvConfPath("/etc/resolv.conf")
.driver("aufs")
.execDriver("native-0.1")
.volumes(ImmutableMap.<String, String>of())
.volumesRW(ImmutableMap.<String, Boolean>of())
.command("")
.status("")
.hostConfig(HostConfig.builder().publishAllPorts(true).build())
.ports(ImmutableList.<Port>of())
.build();
ProviderMetadata providerMetadata = EasyMock.createMock(ProviderMetadata.class);
expect(providerMetadata.getEndpoint()).andReturn("http://127.0.0.1:4243");
replay(providerMetadata);
GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
Supplier<Map<String, ? extends Image>> images = new Supplier<Map<String, ? extends Image>>() {
@Override
public Map<String, ? extends Image> get() {
OperatingSystem os = OperatingSystem.builder()
.description("Ubuntu 12.04 64bit")
.family(OsFamily.UBUNTU)
.version("12.04")
.is64Bit(true)
.build();
return ImmutableMap.of("af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6",
new ImageBuilder()
.ids("af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6")
.name("ubuntu")
.description("Ubuntu 12.04 64bit")
.operatingSystem(os)
.status(Image.Status.AVAILABLE)
.build());
}
};
Supplier<Set<? extends Location>> locations = new Supplier<Set< ? extends Location>>() {
@Override
public Set<? extends Location> get() {
return ImmutableSet.of(
new LocationBuilder()
.id("docker")
.description("http://localhost:2375")
.scope(LocationScope.PROVIDER)
.build()
);
}
};
function = new ContainerToNodeMetadata(providerMetadata, toPortableStatus(), namingConvention, images, locations);
}
private Function<State, NodeMetadata.Status> toPortableStatus() {
StateToStatus function = EasyMock.createMock(StateToStatus.class);
expect(function.apply(anyObject(State.class))).andReturn(NodeMetadata.Status.RUNNING);
replay(function);
return function;
}
public void testVirtualMachineToNodeMetadata() {
Container mockContainer = mockContainer();
NodeMetadata node = function.apply(mockContainer);
verify(mockContainer);
assertEquals(node.getId(), "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9");
assertEquals(node.getGroup(), "hopeful_mclean");
assertEquals(node.getImageId(), "af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6");
assertEquals(node.getLoginPort(), 49199);
assertEquals(node.getPrivateAddresses().size(), 1);
assertEquals(node.getPublicAddresses().size(), 1);
}
@SuppressWarnings("unchecked")
private Container mockContainer() {
Container mockContainer = EasyMock.createMock(Container.class);
expect(mockContainer.getId()).andReturn(container.getId());
expect(mockContainer.getName()).andReturn(container.getName());
expect(mockContainer.getContainerConfig()).andReturn(container.getContainerConfig()).anyTimes();
expect(mockContainer.getNetworkSettings()).andReturn(container.getNetworkSettings()).anyTimes();
expect(mockContainer.getState()).andReturn(container.getState());
expect(mockContainer.getImage()).andReturn(container.getImage()).anyTimes();
replay(mockContainer);
return mockContainer;
}
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* work for additional information regarding copyright ownership.
* The ASF licenses file to You under the Apache License, Version 2.0
* (the "License"); you may not use 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.compute.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import org.easymock.EasyMock;
import org.jclouds.compute.domain.Image;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Unit tests for the {@link org.jclouds.docker.compute.functions.ImageToImage} class.
*/
@Test(groups = "unit", testName = "ImageToImageTest")
public class ImageToImageTest {
private ImageToImage function;
private org.jclouds.docker.domain.Image image;
@BeforeMethod
public void setup() {
image = org.jclouds.docker.domain.Image.builder()
.id("id")
.parent("parent")
.created("created")
.architecture("x86_64")
.repoTags(ImmutableList.of("repoTag1:version"))
.size(0l)
.build();
function = new ImageToImage();
}
public void testImageToImage() {
org.jclouds.docker.domain.Image mockImage = mockImage();
Image image = function.apply(mockImage);
verify(mockImage);
assertEquals(mockImage.getId(), image.getId().toString());
}
@SuppressWarnings("unchecked")
private org.jclouds.docker.domain.Image mockImage() {
org.jclouds.docker.domain.Image mockImage = EasyMock.createMock(org.jclouds.docker.domain.Image.class);
expect(mockImage.getId()).andReturn(image.getId()).anyTimes();
expect(mockImage.getRepoTags()).andReturn(image.getRepoTags()).anyTimes();
expect(mockImage.getArchitecture()).andReturn(image.getArchitecture()).anyTimes();
replay(mockImage);
return mockImage;
}
}

View File

@ -0,0 +1,81 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* work for additional information regarding copyright ownership.
* The ASF licenses file to You under the Apache License, Version 2.0
* (the "License"); you may not use 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.compute.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import org.easymock.EasyMock;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.docker.domain.State;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Unit tests for the {@link StateToStatus} class.
*/
@Test(groups = "unit", testName = "StateToStatusTest")
public class StateToStatusTest {
private StateToStatus function;
@BeforeMethod
public void setup() {
function = new StateToStatus();
}
public void testStateRunningToStatusRunning() {
State mockState = mockStateRunning();
NodeMetadata.Status status = function.apply(mockState);
verify(mockState);
assertEquals(mockState.isRunning(), true);
assertEquals(status, NodeMetadata.Status.RUNNING);
}
public void testStateNotRunningToStatusTerminated() {
State mockState = mockStateNotRunning();
NodeMetadata.Status status = function.apply(mockState);
verify(mockState);
assertEquals(mockState.isRunning(), false);
assertEquals(status, NodeMetadata.Status.TERMINATED);
}
private State mockStateRunning() {
State mockState = EasyMock.createMock(State.class);
expect(mockState.isRunning()).andReturn(true).anyTimes();
replay(mockState);
return mockState;
}
private State mockStateNotRunning() {
State mockState = EasyMock.createMock(State.class);
expect(mockState.isRunning()).andReturn(false).anyTimes();
replay(mockState);
return mockState;
}
}

View File

@ -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.compute.options;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.options.TemplateOptions;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
/**
* Unit tests for the {@link DockerTemplateOptions} class.
*/
@Test(groups = "unit", testName = "DockerTemplateOptionsTest")
public class DockerTemplateOptionsTest {
@Test
public void testHostname() {
TemplateOptions options = new DockerTemplateOptions().hostname("hostname");
assertEquals(options.as(DockerTemplateOptions.class).getHostname(), Optional.of("hostname"));
}
@Test
public void testMemory() {
TemplateOptions options = new DockerTemplateOptions().memory(1024);
assertEquals(options.as(DockerTemplateOptions.class).getMemory(), Optional.of(1024));
}
@Test
public void testCpuShares() {
TemplateOptions options = new DockerTemplateOptions().cpuShares(2);
assertEquals(options.as(DockerTemplateOptions.class).getCpuShares(), Optional.of(2));
}
@Test
public void testVolumes() {
TemplateOptions options = new DockerTemplateOptions().volumes(ImmutableMap.of("/tmp", "/tmp"));
assertEquals(options.as(DockerTemplateOptions.class).getVolumes(), Optional.of(ImmutableMap.of("/tmp", "/tmp")));
}
@Test
public void testDns() {
TemplateOptions options = new DockerTemplateOptions().dns("8.8.8.8");
assertEquals(options.as(DockerTemplateOptions.class).getDns(), Optional.of("8.8.8.8"));
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jclouds.docker.domain.Container;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.jclouds.docker.config.DockerParserModule.ContainerTypeAdapter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* Unit tests for the {@link org.jclouds.docker.config.DockerParserModule} class.
*/
@Test(groups = "unit", testName = "DockerParserModuleTest")
public class DockerParserModuleTest {
private Gson gson;
@BeforeMethod
public void setup() {
gson = new GsonBuilder()
.registerTypeAdapter(Container.class, new ContainerTypeAdapter())
.create();
}
@Test
public void testContainerWithVolumesNull() {
Container container = gson.fromJson(
"{ \"Volumes\": null }", Container.class);
assertNotNull(container);
assertEquals(container.getVolumes(), null);
}
}

View File

@ -0,0 +1,121 @@
/*
* 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 com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.Image;
import org.jclouds.docker.options.BuildOptions;
import org.jclouds.docker.options.CreateImageOptions;
import org.jclouds.docker.options.DeleteImageOptions;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
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;
@Test(groups = "live", testName = "RemoteApiLiveTest", singleThreaded = true)
public class RemoteApiLiveTest extends BaseDockerApiLiveTest {
private static final String BUSYBOX_IMAGE = "busybox";
private Container container = null;
private Image image = null;
@Test
public void testVersion() {
assertEquals(api().getVersion().getVersion(), "1.0.0");
}
@Test(dependsOnMethods = "testVersion")
public void testCreateImage() throws IOException, InterruptedException {
CreateImageOptions options = CreateImageOptions.Builder.fromImage(BUSYBOX_IMAGE);
InputStream createImageStream = api().createImage(options);
consumeStream(createImageStream, false);
image = api().inspectImage(BUSYBOX_IMAGE);
assertNotNull(image);
}
@Test(dependsOnMethods = "testCreateImage")
public void testListImages() {
assertNotNull(api().listImages());
}
@Test(dependsOnMethods = "testListImages")
public void testCreateContainer() throws IOException, InterruptedException {
Config containerConfig = Config.builder().imageId(image.getId())
.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.getId());
}
@Test(dependsOnMethods = "testCreateContainer")
public void testStartContainer() throws IOException, InterruptedException {
api().startContainer(container.getId());
assertTrue(api().inspectContainer(container.getId()).getState().isRunning());
}
@Test(dependsOnMethods = "testStartContainer")
public void testStopContainer() {
api().stopContainer(container.getId());
assertFalse(api().inspectContainer(container.getId()).getState().isRunning());
}
@Test(dependsOnMethods = "testStopContainer", expectedExceptions = NullPointerException.class)
public void testRemoveContainer() {
api().removeContainer(container.getId());
assertFalse(api().inspectContainer(container.getId()).getState().isRunning());
}
@Test(dependsOnMethods = "testRemoveContainer", expectedExceptions = ResourceNotFoundException.class)
public void testDeleteImage() {
InputStream deleteImageStream = api().deleteImage(image.getId());
consumeStream(deleteImageStream, false);
assertNull(api().inspectImage(image.getId()));
}
public void testBuildImage() throws IOException, InterruptedException, URISyntaxException {
BuildOptions options = BuildOptions.Builder.tag("testBuildImage").verbose(false).nocache(false);
InputStream buildImageStream = api().build(new File(Resources.getResource("Dockerfile").toURI()), options);
String buildStream = consumeStream(buildImageStream, false);
Iterable<String> splitted = Splitter.on("\n").split(buildStream.replace("\r", "").trim());
String lastStreamedLine = Iterables.getLast(splitted).trim();
String rawImageId = Iterables.getLast(Splitter.on("Successfully built ").split(lastStreamedLine));
String imageId = rawImageId.substring(0, 11);
Image image = api().inspectImage(imageId);
api().deleteImage(image.getId(), DeleteImageOptions.Builder.force(true));
}
private RemoteApi api() {
return api.getRemoteApi();
}
}

View File

@ -0,0 +1,376 @@
/*
* 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.internal.BaseDockerMockTest;
import org.jclouds.docker.options.BuildOptions;
import org.jclouds.docker.options.CreateImageOptions;
import org.jclouds.docker.options.ListContainerOptions;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
import java.util.Set;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
/**
* Mock tests for the {@link org.jclouds.docker.DockerApi} class.
*/
@Test(groups = "unit", testName = "RemoteApiMockTest")
public class RemoteApiMockTest extends BaseDockerMockTest {
public void testListContainers() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
Set<Container> containers = remoteApi.listContainers();
assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
assertEquals(containers.size(), 1);
} finally {
api.close();
server.shutdown();
}
}
public void testListNonexistentContainers() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
Set<Container> containers = remoteApi.listContainers();
assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
assertTrue(containers.isEmpty());
} finally {
api.close();
server.shutdown();
}
}
@Test(timeOut = 10000l)
public void testListAllContainers() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
Set<Container> containers = remoteApi.listContainers(ListContainerOptions.Builder.all(true));
assertRequestHasParameters(server.takeRequest(), "/containers/json", ImmutableMultimap.of("all", "true"));
assertEquals(containers.size(), 1);
} finally {
api.close();
server.shutdown();
}
}
public void testGetContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/container.json")));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
String containerId = "b03d4cd15b76f8876110615cdeed15eadf77c9beb408d62f1687dcc69192cd6d";
try {
Container container = remoteApi.inspectContainer(containerId);
assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
assertNotNull(container);
assertNotNull(container.getId(), containerId);
assertNotNull(container.getContainerConfig());
assertNotNull(container.getHostConfig());
assertEquals(container.getName(), "/tender_lumiere");
assertEquals(container.getState().isRunning(), true);
} finally {
api.close();
server.shutdown();
}
}
public void testGetNonExistingContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
String containerId = "notExisting";
try {
Container container = remoteApi.inspectContainer(containerId);
assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
} finally {
api.close();
server.shutdown();
}
}
public void testCreateContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/container-creation.json")));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
Config containerConfig = Config.builder().cmd(ImmutableList.of("date"))
.attachStdin(false)
.attachStderr(true)
.attachStdout(true)
.tty(false)
.imageId("base")
.build();
try {
Container container = remoteApi.createContainer("test", containerConfig);
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/create?name=test");
assertNotNull(container);
assertEquals(container.getId(), "c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2");
} finally {
api.close();
server.shutdown();
}
}
public void testRemoveContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(204));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
String containerId = "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9";
try {
remoteApi.removeContainer(containerId);
assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/containers/" + containerId);
} finally {
api.close();
server.shutdown();
}
}
public void testRemoveNonExistingContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
String containerId = "nonExisting";
try {
remoteApi.removeContainer(containerId);
fail("Remove container must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
} finally {
api.close();
server.shutdown();
}
}
public void testStartContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.startContainer("1");
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/start");
} finally {
api.close();
server.shutdown();
}
}
public void testStartNonExistingContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
try {
remoteApi.startContainer("1");
fail("Start container must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
}
} finally {
api.close();
server.shutdown();
}
}
public void testStopContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.stopContainer("1");
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/stop");
} finally {
api.close();
server.shutdown();
}
}
public void testStopNonExistingContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.stopContainer("1");
fail("Stop container must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
} finally {
api.close();
server.shutdown();
}
}
public void testCreateImage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.createImage(CreateImageOptions.Builder.fromImage("base"));
assertRequestHasParameters(server.takeRequest(), "POST", "/images/create", ImmutableMultimap.of("fromImage",
"base"));
} finally {
api.close();
server.shutdown();
}
}
public void testCreateImageFailure() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.createImage(CreateImageOptions.Builder.fromImage("base"));
fail("Create image must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
} finally {
api.close();
server.shutdown();
}
}
public void testDeleteImage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(204));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.deleteImage("1");
assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/images/1");
} finally {
api.close();
server.shutdown();
}
}
public void testDeleteNotExistingImage() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
try {
remoteApi.deleteImage("1");
fail("Delete image must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
} finally {
api.close();
server.shutdown();
}
}
public void testBuildContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
File dockerFile = File.createTempFile("docker", "tmp");
try {
remoteApi.build(dockerFile, BuildOptions.NONE);
assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
} finally {
dockerFile.delete();
api.close();
server.shutdown();
}
}
public void testBuildContainerUsingPayload() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(200));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
File file = File.createTempFile("docker", "tmp");
FileInputStream data = new FileInputStream(file);
Payload payload = Payloads.newInputStreamPayload(data);
payload.getContentMetadata().setContentLength(file.length());
try {
remoteApi.build(payload, BuildOptions.NONE);
assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
} finally {
api.close();
server.shutdown();
}
}
public void testBuildNonexistentContainer() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
DockerApi api = api(server.getUrl("/"));
RemoteApi remoteApi = api.getRemoteApi();
File dockerFile = File.createTempFile("docker", "tmp");
try {
try {
remoteApi.build(dockerFile, BuildOptions.NONE);
fail("Build container must fail on 404");
} catch (ResourceNotFoundException ex) {
// Expected exception
}
} finally {
dockerFile.delete();
api.close();
server.shutdown();
}
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Named;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarUtils;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.beust.jcommander.internal.Lists;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
@Test(groups = "unit", testName = "ArchivesTest")
public class ArchivesTest {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private File tmpDir;
private File outputDir;
private long checkSum;
@BeforeClass
private void init() throws IOException {
tmpDir = Files.createTempDir();
outputDir = Files.createTempDir();
File sampleFile = writeSampleFile("test", "this is a test to tar a hierarchy of folders and files\n");
checkSum = TarUtils.computeCheckSum(Files.asByteSource(sampleFile).read());
}
public void testTarSingleFile() throws Exception {
File archive = Archives.tar(tmpDir, new File(outputDir + File.separator + "test.tar.gz"));
List<File> untarredFiles = unTar(archive, outputDir);
File untarredSampleFile = getOnlyElement(untarredFiles, null);
assertNotNull(untarredSampleFile);
assertTrue(checkSum == TarUtils.computeCheckSum(Files.asByteSource(untarredSampleFile).read()));
}
private List<File> unTar(final File inputFile, final File outputDir) throws Exception {
final List<File> untarredFiles = Lists.newArrayList();
final InputStream is = new FileInputStream(inputFile);
final TarArchiveInputStream tarArchiveInputStream = (TarArchiveInputStream)
new ArchiveStreamFactory().createArchiveInputStream("tar", is);
TarArchiveEntry entry;
while ((entry = (TarArchiveEntry) tarArchiveInputStream.getNextEntry()) != null) {
final File outputFile = new File(outputDir, entry.getName());
if (entry.isDirectory()) {
if (!outputFile.exists()) {
if (!outputFile.mkdirs()) {
throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath()));
}
}
} else {
OutputStream outputFileStream = new FileOutputStream(outputFile);
ByteStreams.copy(tarArchiveInputStream, outputFileStream);
outputFileStream.close();
}
untarredFiles.add(outputFile);
}
tarArchiveInputStream.close();
return untarredFiles;
}
private File writeSampleFile(String fileName, final String contents) {
checkNotNull(fileName, "Provided file name for writing must NOT be null.");
checkNotNull(contents, "Unable to write null contents.");
File sampleFile = new File(tmpDir + File.separator + fileName);
try {
Files.write(contents.getBytes(), sampleFile);
} catch (IOException e) {
logger.error("ERROR trying to write to file '" + fileName + "' - " + e.toString());
Assert.fail();
}
return sampleFile;
}
}

View File

@ -0,0 +1,118 @@
/*
* 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 static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.http.utils.Queries.encodeQueryLine;
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 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;
/**
* Base class for all Docker mock tests.
*/
public class BaseDockerMockTest {
private final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()));
protected String provider;
public BaseDockerMockTest() {
provider = "docker";
}
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;
}
public byte[] payloadFromResource(String resource) {
try {
return toStringAndClose(getClass().getResourceAsStream(resource)).getBytes(Charsets.UTF_8);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
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);
}
}

View File

@ -0,0 +1,29 @@
#
# 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.
#
FROM centos:6.4
MAINTAINER Andrea Turli <andrea.turli@gmail.com>
# RUN yum -y groupinstall 'Development Tools'
RUN yum -y install openssh-server openssh-clients
RUN chkconfig sshd on
RUN service sshd start
RUN echo 'root:password' | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

View File

@ -0,0 +1 @@
{"Id":"c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2","Warnings":null}

View File

@ -0,0 +1,81 @@
{
"Args": [
"-c",
"yum -y install openssh-server openssh-clients"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"/bin/sh",
"-c",
"yum -y install openssh-server openssh-clients"
],
"CpuShares": 0,
"Cpuset": "",
"Domainname": "",
"Entrypoint": null,
"Env": [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"ExposedPorts": null,
"Hostname": "9088c45a9592",
"Image": "1e2d12a45cd57ae3fe3c31ede149d800aaf6a711c61646fad340080f531775c8",
"Memory": 0,
"MemorySwap": 0,
"NetworkDisabled": false,
"OnBuild": [],
"OpenStdin": false,
"PortSpecs": null,
"StdinOnce": false,
"Tty": false,
"User": "",
"Volumes": null,
"WorkingDir": ""
},
"Created": "2014-06-18T08:49:25.36448943Z",
"Driver": "aufs",
"ExecDriver": "native-0.2",
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"Dns": null,
"DnsSearch": null,
"Links": null,
"LxcConf": null,
"NetworkMode": "",
"PortBindings": null,
"Privileged": false,
"PublishAllPorts": false,
"VolumesFrom": null
},
"HostnamePath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/hostname",
"HostsPath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/hosts",
"Id": "be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2",
"Image": "1e2d12a45cd57ae3fe3c31ede149d800aaf6a711c61646fad340080f531775c8",
"MountLabel": "",
"Name": "/tender_lumiere",
"NetworkSettings": {
"Bridge": "docker0",
"Gateway": "172.17.42.1",
"IPAddress": "172.17.0.100",
"IPPrefixLen": 16,
"PortMapping": null,
"Ports": {}
},
"Path": "/bin/sh",
"ProcessLabel": "",
"ResolvConfPath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/resolv.conf",
"State": {
"ExitCode": 0,
"FinishedAt": "0001-01-01T00:00:00Z",
"Paused": false,
"Pid": 16422,
"Running": true,
"StartedAt": "2014-06-18T08:49:25.63685385Z"
},
"Volumes": {},
"VolumesRW": {}
}

View File

@ -0,0 +1,20 @@
[
{
"Command": "/usr/sbin/sshd -D",
"Created": 1395472605,
"Id": "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9",
"Image": "jclouds/ubuntu:latest",
"Names": [
"/hopeful_mclean"
],
"Ports": [
{
"IP": "0.0.0.0",
"PrivatePort": 22,
"PublicPort": 49231,
"Type": "tcp"
}
],
"Status": "Up 55 seconds"
}
]

View File

@ -0,0 +1,34 @@
<?xml version="1.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.
-->
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>- %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<logger name="jclouds.compute" level="debug"/>
<logger name="net.schmizz" level="warn"/>
<logger name="jclouds.wire" level="debug"/>
<logger name="jclouds.headers" level="debug"/>
<logger name="jclouds.ssh" level="debug"/>
</configuration>