mirror of https://github.com/apache/jclouds.git
[JCLOUDS-500] Initial commit for docker
This commit is contained in:
commit
779551c40f
|
@ -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`
|
|
@ -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>
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 container’s configuration (@see BindToJsonPayload)
|
||||
* @return a new container
|
||||
*/
|
||||
@Named("container:create")
|
||||
@POST
|
||||
@Path("/containers/create")
|
||||
Container createContainer(@QueryParam("name") String name, @BinderParam(BindToJsonPayload.class) Config config);
|
||||
|
||||
/**
|
||||
* Return low-level information on the container id
|
||||
* @param containerId The id of the container to get.
|
||||
* @return The details of the container or <code>null</code> if the container with the given id doesn't exist.
|
||||
*/
|
||||
@Named("container:inspect")
|
||||
@GET
|
||||
@Path("/containers/{id}/json")
|
||||
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
|
||||
Container inspectContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* Remove the container by id from the filesystem
|
||||
*
|
||||
* @param containerId The id of the container to be removed.
|
||||
*/
|
||||
@Named("container:delete")
|
||||
@DELETE
|
||||
@Path("/containers/{id}")
|
||||
void removeContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* Remove the container by id from the filesystem
|
||||
*
|
||||
* @param containerId The id of the container to be removed.
|
||||
* @param options the operation’s configuration (@see RemoveContainerOptions)
|
||||
*/
|
||||
@Named("container:delete")
|
||||
@DELETE
|
||||
@Path("/containers/{id}")
|
||||
void removeContainer(@PathParam("id") String containerId, RemoveContainerOptions options);
|
||||
|
||||
/**
|
||||
* Start a container by id.
|
||||
*
|
||||
* @param containerId The id of the container to be started.
|
||||
*/
|
||||
@Named("container:start")
|
||||
@POST
|
||||
@Path("/containers/{id}/start")
|
||||
void startContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* Start a container.
|
||||
*
|
||||
* @param containerId The id of the container to be started.
|
||||
* @param hostConfig the container’s host configuration
|
||||
*/
|
||||
@Named("container:start")
|
||||
@POST
|
||||
@Path("/containers/{id}/start")
|
||||
void startContainer(@PathParam("id") String containerId, @BinderParam(BindToJsonPayload.class) HostConfig hostConfig);
|
||||
|
||||
/**
|
||||
* Stop a container by id.
|
||||
*
|
||||
* @param containerId The id of the container to be stopped.
|
||||
* @return the stream of the stop execution.
|
||||
*/
|
||||
@Named("container:stop")
|
||||
@POST
|
||||
@Path("/containers/{id}/stop")
|
||||
void stopContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* Create a new image from a container’s changes
|
||||
*
|
||||
* @param options the commit’s configuration (@see CommitOptions)
|
||||
* @return a new image created from the current container's status.
|
||||
*/
|
||||
@Named("container:commit")
|
||||
@POST
|
||||
@Path("/commit")
|
||||
Image commit(CommitOptions options);
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Image> listImages();
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @param options the configuration to list images (@see ListImageOptions)
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Image> listImages(ListImageOptions options);
|
||||
|
||||
/**
|
||||
* Inspect an image
|
||||
*
|
||||
* @param imageName The id of the image to inspect.
|
||||
* @return low-level information on the image name
|
||||
*/
|
||||
@Named("image:inspect")
|
||||
@GET
|
||||
@Path("/images/{name}/json")
|
||||
Image inspectImage(@PathParam("name") String imageName);
|
||||
|
||||
/**
|
||||
* Create an image, either by pull it from the registry or by importing it
|
||||
*
|
||||
* @param options the configuration to create an image (@see CreateImageOptions)
|
||||
* @return a stream of the image creation.
|
||||
*/
|
||||
@Named("image:create")
|
||||
@POST
|
||||
@Path("/images/create")
|
||||
InputStream createImage(CreateImageOptions options);
|
||||
|
||||
/**
|
||||
* Delete an image.
|
||||
*
|
||||
* @param name the image name to be deleted
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name);
|
||||
|
||||
/**
|
||||
* Remove the image from the filesystem by name
|
||||
*
|
||||
* @param name the name of the image to be removed
|
||||
* @param options the image deletion's options (@see DeleteImageOptions)
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name, DeleteImageOptions options);
|
||||
|
||||
/**
|
||||
* Build an image from Dockerfile via stdin
|
||||
*
|
||||
* @param inputStream The stream must be a tar archive compressed with one of the following algorithms: identity
|
||||
* (no compression), gzip, bzip2, xz.
|
||||
* @param options the image build's options (@see BuildOptions)
|
||||
* @return a stream of the build execution
|
||||
*/
|
||||
@Named("image:build")
|
||||
@POST
|
||||
@Path("/build")
|
||||
@Headers(keys = "Content-Type", values = "application/tar")
|
||||
InputStream build(Payload inputStream, BuildOptions options);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.jclouds.docker.DockerApiMetadata
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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"]
|
|
@ -0,0 +1 @@
|
|||
{"Id":"c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2","Warnings":null}
|
|
@ -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": {}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
|
@ -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>
|
Loading…
Reference in New Issue