mirror of https://github.com/apache/jclouds.git
Promoted Docker from jclouds-labs
This commit is contained in:
commit
c493e2aa49
|
@ -0,0 +1,89 @@
|
|||
# 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/)
|
||||
- [enable remote access](https://docs.docker.com/engine/quickstart/#bind-docker-to-another-host-port-or-a-unix-socket) to Docker
|
||||
|
||||
### Sample configuration for Linux systems using systemd
|
||||
|
||||
Run following commands on a machine where is the Docker Engine installed.
|
||||
It enables remote access (plain TCP - only for loopback address 127.0.0.1)
|
||||
on standard port `2375`.
|
||||
|
||||
```bash
|
||||
# switch to root account
|
||||
sudo su -
|
||||
|
||||
# create override for docker start-script
|
||||
mkdir /etc/systemd/system/docker.service.d
|
||||
cat << EOT > /etc/systemd/system/docker.service.d/allow-tcp.conf
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/docker daemon -H fd:// -H tcp://
|
||||
EOT
|
||||
|
||||
# reload configuration and restart docker daemon
|
||||
systemctl daemon-reload
|
||||
systemctl restart docker
|
||||
|
||||
# close the 'root' session
|
||||
exit
|
||||
```
|
||||
|
||||
If the `-H fd://` Docker daemon parameter doesn't work on your Linux (e.g. Fedora),
|
||||
then replace it by `-H unix:///var/run/docker.sock`
|
||||
|
||||
Find more details in [Control and configure Docker with systemd](https://docs.docker.com/engine/admin/systemd/) guide.
|
||||
|
||||
### Running live tests
|
||||
|
||||
The `DOCKER_HOST` environment variable has to be configured as it's used as a value for `test.docker.endpoint` system property.
|
||||
|
||||
```
|
||||
export DOCKER_HOST="http://localhost:2375/"
|
||||
mvn -Plive integration-test
|
||||
```
|
||||
|
||||
# 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:
|
||||
- report any issues you find at [jclouds issues](https://issues.apache.org/jira/browse/JCLOUDS)
|
||||
- jclouds-docker has been tested on Mac OSX and Linux. However, it has never been tried on Windows.
|
||||
|
||||
--------------
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
As jclouds docker support is quite new, issues may occasionally arise.
|
||||
You can try to remove all containers to get things going again:
|
||||
|
||||
```bash
|
||||
docker rm -f `docker ps -aq`
|
||||
```
|
|
@ -0,0 +1,192 @@
|
|||
<?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>2.0.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.api-version>1.21</test.docker.api-version>
|
||||
<test.docker.identity>${env.DOCKER_CERT_PATH}/cert.pem</test.docker.identity>
|
||||
<test.docker.credential>${env.DOCKER_CERT_PATH}/key.pem</test.docker.credential>
|
||||
<test.docker.cacert.path>${env.DOCKER_CERT_PATH}/ca.pem</test.docker.cacert.path>
|
||||
<test.docker.endpoint>${env.DOCKER_HOST}</test.docker.endpoint>
|
||||
<test.jclouds.trust-all-certs>false</test.jclouds.trust-all-certs>
|
||||
<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>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.driver</groupId>
|
||||
<artifactId>jclouds-sshj</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.driver</groupId>
|
||||
<artifactId>jclouds-bouncycastle</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.driver</groupId>
|
||||
<artifactId>jclouds-okhttp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</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>
|
||||
<dependency>
|
||||
<groupId>org.jboss.shrinkwrap</groupId>
|
||||
<artifactId>shrinkwrap-depchain</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<type>pom</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>live</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.9.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>regex-property</id>
|
||||
<goals>
|
||||
<goal>regex-property</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<name>test.docker.endpoint</name>
|
||||
<value>${test.docker.endpoint}</value>
|
||||
<regex>tcp</regex>
|
||||
<replacement>https</replacement>
|
||||
<failIfNoMatch>false</failIfNoMatch>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<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>
|
||||
<threadCount>1</threadCount>
|
||||
<systemPropertyVariables>
|
||||
<test.docker.endpoint>${test.docker.endpoint}</test.docker.endpoint>
|
||||
<test.docker.api-version>${test.docker.api-version}</test.docker.api-version>
|
||||
<test.docker.identity>${test.docker.identity}</test.docker.identity>
|
||||
<test.docker.credential>${test.docker.credential}</test.docker.credential>
|
||||
<test.docker.cacert.path>${test.docker.cacert.path}</test.docker.cacert.path>
|
||||
<test.jclouds.trust-all-certs>${test.jclouds.trust-all-certs}</test.jclouds.trust-all-certs>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 java.io.Closeable;
|
||||
|
||||
import org.jclouds.docker.features.ContainerApi;
|
||||
import org.jclouds.docker.features.ImageApi;
|
||||
import org.jclouds.docker.features.MiscApi;
|
||||
import org.jclouds.docker.features.NetworkApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
|
||||
public interface DockerApi extends Closeable {
|
||||
|
||||
@Delegate
|
||||
MiscApi getMiscApi();
|
||||
|
||||
@Delegate
|
||||
ContainerApi getContainerApi();
|
||||
|
||||
@Delegate
|
||||
ImageApi getImageApi();
|
||||
|
||||
@Delegate
|
||||
NetworkApi getNetworkApi();
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
|
||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
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 com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Module;
|
||||
|
||||
@AutoService(ApiMetadata.class)
|
||||
public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
||||
|
||||
public static final String DOCKER_CA_CERT_PATH = "docker.cacert.path";
|
||||
public static final String DOCKER_CA_CERT_DATA = "docker.cacert.data";
|
||||
|
||||
@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_CONNECTION_TIMEOUT, "1200000"); // 15 minutes
|
||||
properties.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
|
||||
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
|
||||
properties.setProperty(DOCKER_CA_CERT_PATH, "");
|
||||
properties.setProperty(DOCKER_CA_CERT_DATA, "");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static class Builder extends BaseHttpApiMetadata.Builder<DockerApi, Builder> {
|
||||
|
||||
protected Builder() {
|
||||
super(DockerApi.class);
|
||||
id("docker")
|
||||
.name("Docker API")
|
||||
.identityName("Path or data for certificate .pem file")
|
||||
.credentialName("Path or data for key .pem file")
|
||||
.documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
|
||||
.version("1.21")
|
||||
.defaultEndpoint("https://127.0.0.1:2376")
|
||||
.defaultProperties(DockerApiMetadata.defaultProperties())
|
||||
.view(typeToken(ComputeServiceContext.class))
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(
|
||||
DockerParserModule.class,
|
||||
DockerHttpApiModule.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,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.config;
|
||||
|
||||
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;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
public class DockerComputeServiceContextModule extends
|
||||
ComputeServiceAdapterContextModule<Container, Hardware, Image, Location> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@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);
|
||||
|
||||
install(new LoginPortLookupModule());
|
||||
}
|
||||
|
||||
}
|
|
@ -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.compute.config;
|
||||
|
||||
import org.jclouds.docker.compute.functions.LoginPortForContainer;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
public class LoginPortLookupModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
// Declare it to initialize the binder allowing duplicates. Users may
|
||||
// provide different functions for the same image in different modules, or
|
||||
// we could provide predefined functions for known images. This allows
|
||||
// users to set their own ones too.
|
||||
loginPortLookupBinder(binder());
|
||||
}
|
||||
|
||||
public static MapBinder<String, LoginPortForContainer> loginPortLookupBinder(Binder binder) {
|
||||
return MapBinder.newMapBinder(binder, String.class, LoginPortForContainer.class).permitDuplicates();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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 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.NetworkSettings;
|
||||
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.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class ContainerToNodeMetadata implements Function<Container, NodeMetadata> {
|
||||
|
||||
/**
|
||||
* This value is used when a container does not have an accessible
|
||||
* login port (i.e. the SSH daemon is not running) due to being
|
||||
* started outside jclouds. Client code should check for this value
|
||||
* when accessing NodeMetadata from Docker.
|
||||
*/
|
||||
private static final Integer NO_LOGIN_PORT = Integer.valueOf(-1);
|
||||
|
||||
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;
|
||||
private final LoginPortForContainer loginPortForContainer;
|
||||
|
||||
@Inject
|
||||
ContainerToNodeMetadata(ProviderMetadata providerMetadata,
|
||||
Function<State, NodeMetadata.Status> toPortableStatus, GroupNamingConvention.Factory namingConvention,
|
||||
Supplier<Map<String, ? extends Image>> images, @Memoized Supplier<Set<? extends Location>> locations,
|
||||
LoginPortForContainer loginPortForContainer) {
|
||||
this.providerMetadata = providerMetadata;
|
||||
this.toPortableStatus = toPortableStatus;
|
||||
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
|
||||
this.images = images;
|
||||
this.locations = locations;
|
||||
this.loginPortForContainer = loginPortForContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata apply(Container container) {
|
||||
String name = cleanUpName(container.name());
|
||||
String group = nodeNamingConvention.extractGroup(name);
|
||||
NodeMetadataBuilder builder = new NodeMetadataBuilder();
|
||||
builder.ids(container.id())
|
||||
.name(name)
|
||||
.group(group)
|
||||
.hostname(container.config().hostname())
|
||||
// TODO Set up hardware
|
||||
.hardware(new HardwareBuilder()
|
||||
.id("")
|
||||
.ram(container.config().memory())
|
||||
.processor(new Processor(container.config().cpuShares(), container.config().cpuShares()))
|
||||
.build());
|
||||
builder.status(toPortableStatus.apply(container.state()));
|
||||
builder.loginPort(loginPortForContainer.apply(container).or(NO_LOGIN_PORT));
|
||||
builder.publicAddresses(getPublicIpAddresses(container));
|
||||
builder.privateAddresses(getPrivateIpAddresses(container));
|
||||
builder.location(Iterables.getOnlyElement(locations.get()));
|
||||
String imageId = container.image();
|
||||
builder.imageId(imageId);
|
||||
if (images.get().containsKey(imageId)) {
|
||||
Image image = images.get().get(imageId);
|
||||
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) {
|
||||
// A container can be attached to multiple networks. It can therefore have multiple private
|
||||
// IPs. The NetworkSettings.ipAddress might in fact be blank, with the only IP being on
|
||||
// network objects.
|
||||
if (container.networkSettings() == null) return ImmutableList.of();
|
||||
ImmutableSet.Builder<String> builder = ImmutableSet.<String>builder();
|
||||
NetworkSettings settings = container.networkSettings();
|
||||
if (settings.ipAddress() != null && settings.ipAddress().length() > 0) {
|
||||
builder.add(settings.ipAddress());
|
||||
}
|
||||
if (settings.networks() != null) {
|
||||
for (Map.Entry<String, NetworkSettings.Details> entry : settings.networks().entrySet()) {
|
||||
String ipAddress = entry.getValue().ipAddress();
|
||||
if (ipAddress != null && ipAddress.length() > 0) {
|
||||
builder.add(ipAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private List<String> getPublicIpAddresses(Container container) {
|
||||
String dockerIpAddress;
|
||||
if (container.node().isPresent()) {
|
||||
dockerIpAddress = container.node().get().ip();
|
||||
} else {
|
||||
dockerIpAddress = URI.create(providerMetadata.getEndpoint()).getHost();
|
||||
}
|
||||
return ImmutableList.of(dockerIpAddress);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.docker.domain.Container;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@Beta
|
||||
public class CustomLoginPortFromImage implements LoginPortForContainer {
|
||||
|
||||
private final Map<String, Set<LoginPortForContainer>> imageToPortLookup;
|
||||
|
||||
@Inject
|
||||
CustomLoginPortFromImage(Map<String, Set<LoginPortForContainer>> imageToPortLookup) {
|
||||
this.imageToPortLookup = imageToPortLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> apply(final Container container) {
|
||||
Map<String, Set<LoginPortForContainer>> matchingFunctions = Maps.filterKeys(imageToPortLookup,
|
||||
new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
return container.config().image().matches(input);
|
||||
}
|
||||
});
|
||||
|
||||
// We allow to provide several forms in the image-to-function map:
|
||||
// - redis
|
||||
// - redis:12
|
||||
// - owner/redis:12
|
||||
// - registry:5000/owner/redis:12
|
||||
// We consider the longest match first, as it is the more accurate one
|
||||
List<String> sortedImages = new ArrayList<String>(matchingFunctions.keySet());
|
||||
Collections.sort(sortedImages, LongestStringFirst);
|
||||
|
||||
for (String currentImage : sortedImages) {
|
||||
Set<LoginPortForContainer> functions = matchingFunctions.get(currentImage);
|
||||
for (LoginPortForContainer function : functions) {
|
||||
Optional<Integer> port = function.apply(container);
|
||||
if (port.isPresent()) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
private static final Comparator<String> LongestStringFirst = new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String s1, String s2) {
|
||||
return s2.length() - s1.length();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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 javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
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 com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
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 firstRepoTag = Iterables.getFirst(from.repoTags(), "<none>");
|
||||
final int versionSeparatorPos = firstRepoTag.lastIndexOf(':');
|
||||
|
||||
final String name;
|
||||
final String osVersion;
|
||||
if (versionSeparatorPos > -1) {
|
||||
name = firstRepoTag.substring(0, versionSeparatorPos);
|
||||
osVersion = firstRepoTag.substring(versionSeparatorPos + 1);
|
||||
} else {
|
||||
name = firstRepoTag;
|
||||
osVersion = firstRepoTag;
|
||||
}
|
||||
logger.debug("os version for item: %s is %s", firstRepoTag, osVersion);
|
||||
|
||||
OsFamily osFamily = osFamily().apply(firstRepoTag);
|
||||
|
||||
OperatingSystem os = OperatingSystem.builder()
|
||||
.description(firstRepoTag)
|
||||
.family(osFamily)
|
||||
.version(osVersion)
|
||||
.is64Bit(is64bit(from))
|
||||
.build();
|
||||
|
||||
return new ImageBuilder()
|
||||
.ids(from.id())
|
||||
.name(name)
|
||||
.description(firstRepoTag)
|
||||
.operatingSystem(os)
|
||||
.status(Image.Status.AVAILABLE)
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean is64bit(org.jclouds.docker.domain.Image inspectedImage) {
|
||||
if (inspectedImage.architecture() == null) return true;
|
||||
return inspectedImage.architecture().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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.compute.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.docker.compute.functions.LoginPortForContainer.LoginPortLookupChain;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
@Beta
|
||||
@ImplementedBy(LoginPortLookupChain.class)
|
||||
public interface LoginPortForContainer extends Function<Container, Optional<Integer>> {
|
||||
|
||||
@Beta
|
||||
static final class LoginPortLookupChain implements LoginPortForContainer {
|
||||
private final PublicPortForContainerPort publicPortForContainerPort;
|
||||
private final CustomLoginPortFromImage customLoginPortFromImage;
|
||||
|
||||
@Inject
|
||||
LoginPortLookupChain(CustomLoginPortFromImage customLoginPortFromImage) {
|
||||
this.publicPortForContainerPort = new PublicPortForContainerPort(22);
|
||||
this.customLoginPortFromImage = customLoginPortFromImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> apply(Container input) {
|
||||
Optional<Integer> loginPort = publicPortForContainerPort.apply(input);
|
||||
return loginPort.isPresent() ? loginPort : customLoginPortFromImage.apply(input);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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.functions;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Port;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
@Beta
|
||||
public class PublicPortForContainerPort implements LoginPortForContainer {
|
||||
|
||||
private final int containerPort;
|
||||
|
||||
public PublicPortForContainerPort(int containerPort) {
|
||||
this.containerPort = containerPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> apply(Container container) {
|
||||
if (container.networkSettings() != null) {
|
||||
Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
|
||||
if (ports != null && ports.containsKey(containerPort + "/tcp")) {
|
||||
return Optional.of(Integer.parseInt(getOnlyElement(ports.get(containerPort + "/tcp")).get("HostPort")));
|
||||
}
|
||||
// this is needed in case the container list is coming from
|
||||
// listContainers
|
||||
} else if (container.ports() != null) {
|
||||
for (Port port : container.ports()) {
|
||||
if (port.privatePort() == containerPort) {
|
||||
return Optional.of(port.publicPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
}
|
|
@ -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.running() ? Status.RUNNING : Status.TERMINATED;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,780 @@
|
|||
/*
|
||||
* 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 com.google.common.base.Objects.equal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.internal.NullSafeCopies;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
/**
|
||||
* Contains options supported by the
|
||||
* {@link org.jclouds.compute.ComputeService#createNodesInGroup(String, int, TemplateOptions)
|
||||
* createNodes} operation on the <em>docker</em> provider.
|
||||
*
|
||||
* <h2>Usage</h2>
|
||||
*
|
||||
* The recommended way to instantiate a DockerTemplateOptions object is to
|
||||
* statically import {@code DockerTemplateOptions.Builder.*} and invoke one of
|
||||
* the static creation methods, followed by an instance mutator if needed.
|
||||
*
|
||||
* <pre>
|
||||
* {@code import static org.jclouds.docker.compute.options.DockerTemplateOptions.Builder.*;
|
||||
*
|
||||
* ComputeService api = // get connection
|
||||
* templateBuilder.options(inboundPorts(22, 80, 8080, 443));
|
||||
* Set<? extends NodeMetadata> set = api.createNodesInGroup(tag, 2, templateBuilder.build());}
|
||||
* </pre>
|
||||
*
|
||||
* <h2>Advanced Usage</h2>
|
||||
* <p>
|
||||
* In addition to basic configuration through its methods, this class also
|
||||
* provides possibility to work directly with Docker API configuration object (
|
||||
* {@link Config.Builder}). When the
|
||||
* {@link #configBuilder(org.jclouds.docker.domain.Config.Builder)} is used to
|
||||
* configure not-<code>null</code> configBuilder, then this configuration object
|
||||
* takes precedence over the other configuration in this class (i.e. the other
|
||||
* config entries are not used)
|
||||
* </p>
|
||||
* <p>
|
||||
* Note: The {@code image} property in the provided {@link Config.Builder} is rewritten by a placeholder value.
|
||||
* The real value is configured by ComputeServiceAdapter.
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* {@code import static org.jclouds.docker.compute.options.DockerTemplateOptions.Builder.*;
|
||||
*
|
||||
* ComputeService api = // get connection
|
||||
* DockerTemplateOptions options = DockerTemplateOptions.Builder
|
||||
* .configBuilder(
|
||||
* Config.builder().env(ImmutableList.<String> of("SSH_PORT=8822"))
|
||||
* .hostConfig(HostConfig.builder().networkMode("host").build()));
|
||||
* templateBuilder.options(options);
|
||||
* Set<? extends NodeMetadata> set = api.createNodesInGroup("sample-group", 1, templateBuilder.build());}
|
||||
* </pre>
|
||||
*/
|
||||
public class DockerTemplateOptions extends TemplateOptions implements Cloneable {
|
||||
|
||||
private static final String NO_IMAGE = "jclouds-placeholder-for-image";
|
||||
|
||||
protected List<String> dns = ImmutableList.of();
|
||||
@Nullable protected String hostname;
|
||||
@Nullable protected Integer memory;
|
||||
@Nullable protected Integer cpuShares;
|
||||
@Nullable List<String> entrypoint;
|
||||
@Nullable List<String> commands;
|
||||
protected Map<String, String> volumes = ImmutableMap.of();
|
||||
@Nullable protected List<String> env;
|
||||
protected Map<Integer, Integer> portBindings = ImmutableMap.of();
|
||||
@Nullable protected String networkMode;
|
||||
protected Map<String, String> extraHosts = ImmutableMap.of();
|
||||
protected List<String> volumesFrom = ImmutableList.of();
|
||||
protected boolean privileged;
|
||||
protected boolean openStdin;
|
||||
protected Config.Builder configBuilder;
|
||||
|
||||
@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);
|
||||
eTo.volumes(volumes);
|
||||
eTo.hostname(hostname);
|
||||
eTo.dns(dns);
|
||||
eTo.memory(memory);
|
||||
eTo.cpuShares(cpuShares);
|
||||
eTo.entrypoint(entrypoint);
|
||||
eTo.commands(commands);
|
||||
eTo.env(env);
|
||||
eTo.portBindings(portBindings);
|
||||
eTo.networkMode(networkMode);
|
||||
eTo.extraHosts(extraHosts);
|
||||
eTo.volumesFrom(volumesFrom);
|
||||
eTo.privileged(privileged);
|
||||
eTo.openStdin(openStdin);
|
||||
eTo.configBuilder(configBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@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.cpuShares, that.cpuShares) &&
|
||||
equal(this.entrypoint, that.entrypoint) &&
|
||||
equal(this.commands, that.commands) &&
|
||||
equal(this.env, that.env) &&
|
||||
equal(this.portBindings, that.portBindings) &&
|
||||
equal(this.networkMode, that.networkMode) &&
|
||||
equal(this.extraHosts, that.extraHosts) &&
|
||||
equal(this.volumesFrom, that.volumesFrom) &&
|
||||
equal(this.privileged, that.privileged) &&
|
||||
equal(this.openStdin, that.openStdin) &&
|
||||
buildersEqual(this.configBuilder, that.configBuilder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two Config.Builder instances.
|
||||
*/
|
||||
private boolean buildersEqual(Config.Builder b1, Config.Builder b2) {
|
||||
return b1 == b2 || (b1 != null && b2 != null && b1.build().equals(b2.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(super.hashCode(), volumes, hostname, dns, memory, entrypoint, commands, cpuShares, env,
|
||||
portBindings, networkMode, extraHosts, volumesFrom, privileged, openStdin, configBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this)
|
||||
.add("volumes", volumes)
|
||||
.add("hostname", hostname)
|
||||
.add("dns", dns)
|
||||
.add("memory", memory)
|
||||
.add("cpuShares", cpuShares)
|
||||
.add("entrypoint", entrypoint)
|
||||
.add("commands", commands)
|
||||
.add("env", env)
|
||||
.add("portBindings", portBindings)
|
||||
.add("networkMode", networkMode)
|
||||
.add("extraHosts", extraHosts)
|
||||
.add("volumesFrom", volumesFrom)
|
||||
.add("privileged", privileged)
|
||||
.add("openStdin", openStdin)
|
||||
.add("configBuilder", configBuilder)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public DockerTemplateOptions volumes(Map<String, String> volumes) {
|
||||
this.volumes = NullSafeCopies.copyOf(volumes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions dns(Iterable<String> dns) {
|
||||
this.dns = NullSafeCopies.copyOf(dns);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions dns(String...dns) {
|
||||
this.dns = NullSafeCopies.copyOf(dns);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions hostname(@Nullable String hostname) {
|
||||
this.hostname = hostname;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions memory(@Nullable Integer memory) {
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions entrypoint(Iterable<String> entrypoint) {
|
||||
this.entrypoint = NullSafeCopies.copyWithNullOf(entrypoint);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions entrypoint(String... entrypoint) {
|
||||
this.entrypoint = NullSafeCopies.copyWithNullOf(entrypoint);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions commands(Iterable<String> commands) {
|
||||
this.commands = NullSafeCopies.copyWithNullOf(commands);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions commands(String...commands) {
|
||||
this.commands = NullSafeCopies.copyWithNullOf(commands);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions cpuShares(@Nullable Integer cpuShares) {
|
||||
this.cpuShares = cpuShares;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions env(Iterable<String> env) {
|
||||
this.env = NullSafeCopies.copyWithNullOf(env);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DockerTemplateOptions env(String...env) {
|
||||
this.env = NullSafeCopies.copyWithNullOf(env);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port bindings between the Docker host and a container.
|
||||
* <p>
|
||||
* The {@link Map} keys are host ports number, and the value for an entry is the
|
||||
* container port number. This is the same order as the arguments for the
|
||||
* {@code --publish} command-line option to {@code docker run} which is
|
||||
* {@code hostPort:containerPort}.
|
||||
*
|
||||
* @param portBindings the map of host to container port bindings
|
||||
*/
|
||||
public DockerTemplateOptions portBindings(Map<Integer, Integer> portBindings) {
|
||||
this.portBindings = NullSafeCopies.copyOf(portBindings);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the networking mode for the container.
|
||||
* <p>
|
||||
* Supported values are: {@code bridge}, {@code none}, {@code host},
|
||||
* {@code networkname}, {@code networkid} or {@code container:[name|id]}
|
||||
*
|
||||
* @param networkMode
|
||||
* @return this instance
|
||||
*/
|
||||
public DockerTemplateOptions networkMode(@Nullable String networkMode) {
|
||||
this.networkMode = networkMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra hosts file entries for a container.
|
||||
* <p>
|
||||
* The {@link Map} keys are host names, and the value is an IP address that
|
||||
* can be accessed by the container. This is the same order as the arguments for the
|
||||
* {@code --add-host} command-line option to {@code docker run}.
|
||||
*
|
||||
* @param extraHosts the map of host names to IP addresses
|
||||
*/
|
||||
public DockerTemplateOptions extraHosts(Map<String, String> extraHosts) {
|
||||
this.extraHosts = NullSafeCopies.copyOf(extraHosts);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set list of containers to mount volumes from onto this container.
|
||||
*
|
||||
* @param volumesFrom the list of container names
|
||||
*/
|
||||
public DockerTemplateOptions volumesFrom(Iterable<String> volumesFrom) {
|
||||
this.volumesFrom = NullSafeCopies.copyOf(volumesFrom);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Docker containers are unprivileged and cannot execute privileged operations or access certain
|
||||
* host devices.
|
||||
*
|
||||
* @param privileged Whether the container should run in privileged mode or not
|
||||
* @return this instance
|
||||
*/
|
||||
public DockerTemplateOptions privileged(boolean privileged) {
|
||||
this.privileged = privileged;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep {@code STDIN} open when running interactive workloads in the container.
|
||||
*
|
||||
* @param openStdin Whether the container should keep STDIN open
|
||||
* @return this instance
|
||||
*/
|
||||
public DockerTemplateOptions openStdin(boolean openStdin) {
|
||||
this.openStdin = openStdin;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets Config.Builder configuration object, which can be used as
|
||||
* a replacement for all the other settings from this class. Some values in
|
||||
* the provided Config.Builder instance (the image name for instance) can be
|
||||
* ignored or their value can be changed.
|
||||
*
|
||||
* @param configBuilder
|
||||
* Config.Builder instance. This instance can be changed in this
|
||||
* method!
|
||||
*/
|
||||
public DockerTemplateOptions configBuilder(Config.Builder configBuilder) {
|
||||
this.configBuilder = configBuilder != null
|
||||
? Config.builder().fromConfig(configBuilder.image(NO_IMAGE).build())
|
||||
: null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, String> getVolumes() { return volumes; }
|
||||
|
||||
public List<String> getDns() { return dns; }
|
||||
|
||||
public List<String> getVolumesFrom() { return volumesFrom; }
|
||||
|
||||
public String getHostname() { return hostname; }
|
||||
|
||||
public Integer getMemory() { return memory; }
|
||||
|
||||
public List<String> getEntrypoint() { return entrypoint; }
|
||||
|
||||
public List<String> getCommands() { return commands; }
|
||||
|
||||
public Integer getCpuShares() { return cpuShares; }
|
||||
|
||||
public List<String> getEnv() { return env; }
|
||||
|
||||
public Map<Integer, Integer> getPortBindings() { return portBindings; }
|
||||
|
||||
public String getNetworkMode() { return networkMode; }
|
||||
|
||||
public Map<String, String> getExtraHosts() { return extraHosts; }
|
||||
|
||||
public boolean getPrivileged() { return privileged; }
|
||||
|
||||
public boolean getOpenStdin() { return openStdin; }
|
||||
|
||||
public Config.Builder getConfigBuilder() { return configBuilder; }
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#volumes(Map)
|
||||
*/
|
||||
public static DockerTemplateOptions volumes(Map<String, String> volumes) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.volumes(volumes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#dns(String...)
|
||||
*/
|
||||
public static DockerTemplateOptions dns(String...dns) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.dns(dns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#dns(List)
|
||||
*/
|
||||
public static DockerTemplateOptions dns(Iterable<String> dns) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.dns(dns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#hostname(String)
|
||||
*/
|
||||
public static DockerTemplateOptions hostname(@Nullable String hostname) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.hostname(hostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#memory(Integer)
|
||||
*/
|
||||
public static DockerTemplateOptions memory(@Nullable Integer memory) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.memory(memory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#entrypoint(String...)
|
||||
*/
|
||||
public static DockerTemplateOptions entrypoint(String...entrypoint) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.entrypoint(entrypoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#entrypoint(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions entrypoint(Iterable<String> entrypoint) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.entrypoint(entrypoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#commands(String...)
|
||||
*/
|
||||
public static DockerTemplateOptions commands(String...commands) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.commands(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#commands(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions commands(Iterable<String> commands) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.commands(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#cpuShares(Integer)
|
||||
*/
|
||||
public static DockerTemplateOptions cpuShares(@Nullable Integer cpuShares) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.cpuShares(cpuShares);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#env(String...)
|
||||
*/
|
||||
public static DockerTemplateOptions env(String...env) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.env(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#env(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions env(Iterable<String> env) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.env(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#portBindings(Map)
|
||||
*/
|
||||
public static DockerTemplateOptions portBindings(Map<Integer, Integer> portBindings) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.portBindings(portBindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#networkMode(String)
|
||||
*/
|
||||
public static DockerTemplateOptions networkMode(@Nullable String networkMode) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.networkMode(networkMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#extraHosts(Map)
|
||||
*/
|
||||
public static DockerTemplateOptions extraHosts(Map<String, String> extraHosts) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.extraHosts(extraHosts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#privileged(boolean)
|
||||
*/
|
||||
public static DockerTemplateOptions privileged(boolean privileged) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.privileged(privileged);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#openStdin(boolean)
|
||||
*/
|
||||
public static DockerTemplateOptions openStdin(boolean openStdin) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.openStdin(openStdin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#configBuilder(Config.Builder)
|
||||
*/
|
||||
public static DockerTemplateOptions configBuilder(Config.Builder configBuilder) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.configBuilder(configBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#volumesFrom(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions volumesFrom(Iterable<String> volumesFrom) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.volumesFrom(volumesFrom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#inboundPorts(int...)
|
||||
*/
|
||||
public static DockerTemplateOptions inboundPorts(int... ports) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.inboundPorts(ports);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#blockOnPort(int, int)
|
||||
*/
|
||||
public static DockerTemplateOptions blockOnPort(int port, int seconds) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.blockOnPort(port, seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#installPrivateKey(String)
|
||||
*/
|
||||
public static DockerTemplateOptions installPrivateKey(String rsaKey) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.installPrivateKey(rsaKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#authorizePublicKey(String)
|
||||
*/
|
||||
public static DockerTemplateOptions authorizePublicKey(String rsaKey) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.authorizePublicKey(rsaKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#userMetadata(Map)
|
||||
*/
|
||||
public static DockerTemplateOptions userMetadata(Map<String, String> userMetadata) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.userMetadata(userMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#nodeNames(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions nodeNames(Iterable<String> nodeNames) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.nodeNames(nodeNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#networks(Iterable)
|
||||
*/
|
||||
public static DockerTemplateOptions networks(Iterable<String> networks) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.networks(networks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#overrideLoginUser(String)
|
||||
*/
|
||||
public static DockerTemplateOptions overrideLoginUser(String user) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.overrideLoginUser(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#overrideLoginPassword(String)
|
||||
*/
|
||||
public static DockerTemplateOptions overrideLoginPassword(String password) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.overrideLoginPassword(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#overrideLoginPrivateKey(String)
|
||||
*/
|
||||
public static DockerTemplateOptions overrideLoginPrivateKey(String privateKey) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.overrideLoginPrivateKey(privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#overrideAuthenticateSudo(boolean)
|
||||
*/
|
||||
public static DockerTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.overrideAuthenticateSudo(authenticateSudo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#overrideLoginCredentials(LoginCredentials)
|
||||
*/
|
||||
public static DockerTemplateOptions overrideLoginCredentials(LoginCredentials credentials) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
return options.overrideLoginCredentials(credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#blockUntilRunning(boolean)
|
||||
*/
|
||||
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,353 @@
|
|||
/*
|
||||
* 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.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
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.options.TemplateOptions;
|
||||
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.ContainerSummary;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.ImageSummary;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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> {
|
||||
|
||||
|
||||
/**
|
||||
* Some Docker versions returns host prefix even for images from Docker hub in repoTags field. We use this constant
|
||||
* to correctly identify requested image name.
|
||||
*/
|
||||
public static final String PREFIX_DOCKER_HUB_HOST = "docker.io/";
|
||||
|
||||
/**
|
||||
* (Optional) Suffix used, when image version is not used during searching images.
|
||||
*/
|
||||
public static final String SUFFIX_LATEST_VERSION = ":latest";
|
||||
|
||||
private static final String PATTERN_IMAGE_PREFIX = "^(" + Pattern.quote(PREFIX_DOCKER_HUB_HOST) + ")?";
|
||||
private static final String PATTERN_IMAGE_SUFFIX = "(" + Pattern.quote(SUFFIX_LATEST_VERSION) + ")?$";
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final DockerApi api;
|
||||
|
||||
@Inject
|
||||
public DockerComputeServiceAdapter(DockerApi api) {
|
||||
this.api = checkNotNull(api, "api");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public NodeAndInitialCredentials<Container> createNodeWithGroupEncodedIntoName(String group, String name,
|
||||
Template template) {
|
||||
checkNotNull(template, "template was null");
|
||||
TemplateOptions options = template.getOptions();
|
||||
checkNotNull(options, "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().getOptionalPassword().or("password");
|
||||
|
||||
DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(options);
|
||||
|
||||
Config containerConfig = null;
|
||||
Config.Builder containerConfigBuilder = templateOptions.getConfigBuilder();
|
||||
if (containerConfigBuilder == null) {
|
||||
containerConfigBuilder = Config.builder().image(imageId);
|
||||
|
||||
containerConfigBuilder.entrypoint(templateOptions.getEntrypoint());
|
||||
containerConfigBuilder.cmd(templateOptions.getCommands());
|
||||
containerConfigBuilder.memory(templateOptions.getMemory());
|
||||
containerConfigBuilder.hostname(templateOptions.getHostname());
|
||||
containerConfigBuilder.cpuShares(templateOptions.getCpuShares());
|
||||
containerConfigBuilder.openStdin(templateOptions.getOpenStdin());
|
||||
containerConfigBuilder.env(templateOptions.getEnv());
|
||||
|
||||
if (!templateOptions.getVolumes().isEmpty()) {
|
||||
Map<String, Object> volumes = Maps.newLinkedHashMap();
|
||||
for (String containerDir : templateOptions.getVolumes().values()) {
|
||||
volumes.put(containerDir, Maps.newHashMap());
|
||||
}
|
||||
containerConfigBuilder.volumes(volumes);
|
||||
}
|
||||
|
||||
HostConfig.Builder hostConfigBuilder = HostConfig.builder()
|
||||
.publishAllPorts(true)
|
||||
.privileged(templateOptions.getPrivileged());
|
||||
|
||||
if (!templateOptions.getPortBindings().isEmpty()) {
|
||||
Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
|
||||
for (Map.Entry<Integer, Integer> entry : templateOptions.getPortBindings().entrySet()) {
|
||||
portBindings.put(entry.getValue() + "/tcp",
|
||||
Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostIp", "0.0.0.0", "HostPort", Integer.toString(entry.getKey()))));
|
||||
}
|
||||
hostConfigBuilder.portBindings(portBindings);
|
||||
}
|
||||
|
||||
if (!templateOptions.getDns().isEmpty()) {
|
||||
hostConfigBuilder.dns(templateOptions.getDns());
|
||||
}
|
||||
|
||||
if (!templateOptions.getExtraHosts().isEmpty()) {
|
||||
List<String> extraHosts = Lists.newArrayList();
|
||||
for (Map.Entry<String, String> entry : templateOptions.getExtraHosts().entrySet()) {
|
||||
extraHosts.add(entry.getKey() + ":" + entry.getValue());
|
||||
}
|
||||
hostConfigBuilder.extraHosts(extraHosts);
|
||||
}
|
||||
|
||||
if (!templateOptions.getVolumes().isEmpty()) {
|
||||
for (Map.Entry<String, String> entry : templateOptions.getVolumes().entrySet()) {
|
||||
hostConfigBuilder.binds(ImmutableList.of(entry.getKey() + ":" + entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!templateOptions.getVolumesFrom().isEmpty()) {
|
||||
hostConfigBuilder.volumesFrom(templateOptions.getVolumesFrom());
|
||||
}
|
||||
|
||||
hostConfigBuilder.networkMode(templateOptions.getNetworkMode());
|
||||
|
||||
containerConfigBuilder.hostConfig(hostConfigBuilder.build());
|
||||
|
||||
// add the inbound ports into exposed ports map
|
||||
containerConfig = containerConfigBuilder.build();
|
||||
Map<String, Object> exposedPorts = Maps.newHashMap();
|
||||
if (containerConfig.exposedPorts() == null) {
|
||||
exposedPorts.putAll(containerConfig.exposedPorts());
|
||||
}
|
||||
for (int inboundPort : templateOptions.getInboundPorts()) {
|
||||
String portKey = inboundPort + "/tcp";
|
||||
if (!exposedPorts.containsKey(portKey)) {
|
||||
exposedPorts.put(portKey, Maps.newHashMap());
|
||||
}
|
||||
}
|
||||
containerConfigBuilder.exposedPorts(exposedPorts);
|
||||
|
||||
// build once more after setting inboundPorts
|
||||
containerConfig = containerConfigBuilder.build();
|
||||
|
||||
// finally update port bindings
|
||||
Map<String, List<Map<String, String>>> portBindings = Maps.newHashMap();
|
||||
Map<String, List<Map<String, String>>> existingBindings = containerConfig.hostConfig().portBindings();
|
||||
if (existingBindings != null) {
|
||||
portBindings.putAll(existingBindings);
|
||||
}
|
||||
for (String exposedPort : containerConfig.exposedPorts().keySet()) {
|
||||
if (!portBindings.containsKey(exposedPort)) {
|
||||
portBindings.put(exposedPort, Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostIp", "0.0.0.0")));
|
||||
}
|
||||
}
|
||||
hostConfigBuilder = HostConfig.builder().fromHostConfig(containerConfig.hostConfig());
|
||||
hostConfigBuilder.portBindings(portBindings);
|
||||
containerConfigBuilder.hostConfig(hostConfigBuilder.build());
|
||||
} else {
|
||||
containerConfigBuilder.image(imageId);
|
||||
}
|
||||
|
||||
containerConfig = containerConfigBuilder.build();
|
||||
|
||||
logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
|
||||
Container container = api.getContainerApi().createContainer(name, containerConfig);
|
||||
logger.trace("<< container(%s)", container.id());
|
||||
|
||||
if (templateOptions.getNetworks() != null) {
|
||||
logger.debug(">> connecting container(%s) to networks(%s)", container.id(), Iterables.toString(templateOptions.getNetworks()));
|
||||
for (String networkIdOrName : templateOptions.getNetworks()) {
|
||||
api.getNetworkApi().connectContainerToNetwork(networkIdOrName, container.id());
|
||||
}
|
||||
logger.trace("<< connected(%s)", container.id());
|
||||
}
|
||||
|
||||
HostConfig hostConfig = containerConfig.hostConfig();
|
||||
|
||||
logger.debug(">> starting container(%s) with hostConfig(%s)", container.id(), hostConfig);
|
||||
api.getContainerApi().startContainer(container.id(), hostConfig);
|
||||
logger.trace("<< started(%s)", container.id());
|
||||
|
||||
container = api.getContainerApi().inspectContainer(container.id());
|
||||
if (container.state().exitCode() != 0) {
|
||||
destroyNode(container.id());
|
||||
throw new IllegalStateException(String.format("Container %s has not started correctly", container.id()));
|
||||
}
|
||||
return new NodeAndInitialCredentials(container, container.id(),
|
||||
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(2, 1)).ram(2048).build());
|
||||
hardware.add(new HardwareBuilder().ids("large").hypervisor("lxc").name("large").processor(new Processor(2, 1)).ram(3072).build());
|
||||
return hardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method based on {@link org.jclouds.docker.features.ImageApi#listImages()}. It retrieves additional
|
||||
* information by inspecting each image.
|
||||
*
|
||||
* @see org.jclouds.compute.ComputeServiceAdapter#listImages()
|
||||
*/
|
||||
@Override
|
||||
public Set<Image> listImages() {
|
||||
Set<Image> images = Sets.newHashSet();
|
||||
for (ImageSummary imageSummary : api.getImageApi().listImages()) {
|
||||
// less efficient than just listImages but returns richer json that needs repoTags coming from listImages
|
||||
Image inspected = api.getImageApi().inspectImage(imageSummary.id());
|
||||
inspected = Image.create(inspected.id(), inspected.author(), inspected.comment(), inspected.config(),
|
||||
inspected.containerConfig(), inspected.parent(), inspected.created(), inspected.container(),
|
||||
inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
|
||||
inspected.virtualSize(), imageSummary.repoTags());
|
||||
images.add(inspected);
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(final String imageIdOrName) {
|
||||
checkNotNull(imageIdOrName);
|
||||
if (imageIdOrName.startsWith("sha256")) {
|
||||
// less efficient than just inspectImage but listImages return repoTags
|
||||
return find(listImages(), new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
// Only attempt match on id as we should try to pull again anyway if using name
|
||||
return input.id().equals(imageIdOrName);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
// Image is not cached or getting image by name so try to pull it
|
||||
api.getImageApi().createImage(CreateImageOptions.Builder.fromImage(imageIdOrName));
|
||||
|
||||
// as above this ensure repotags are returned
|
||||
return find(listImages(), createPredicateMatchingRepoTags(imageIdOrName), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Container> listNodes() {
|
||||
Set<Container> containers = Sets.newHashSet();
|
||||
for (ContainerSummary containerSummary : api.getContainerApi().listContainers(ListContainerOptions.Builder.all(true))) {
|
||||
// less efficient than just listNodes but returns richer json
|
||||
containers.add(api.getContainerApi().inspectContainer(containerSummary.id()));
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Container> listNodesByIds(final Iterable<String> ids) {
|
||||
Set<Container> containers = Sets.newHashSet();
|
||||
for (String id : ids) {
|
||||
containers.add(api.getContainerApi().inspectContainer(id));
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Location> listLocations() {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getNode(String id) {
|
||||
return api.getContainerApi().inspectContainer(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNode(String id) {
|
||||
api.getContainerApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNode(String id) {
|
||||
api.getContainerApi().stopContainer(id);
|
||||
api.getContainerApi().startContainer(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeNode(String id) {
|
||||
api.getContainerApi().unpause(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspendNode(String id) {
|
||||
api.getContainerApi().pause(id);
|
||||
}
|
||||
|
||||
protected static Predicate<Image> createPredicateMatchingRepoTags(final String imageIdOrName) {
|
||||
final Pattern imgPattern = Pattern
|
||||
.compile(PATTERN_IMAGE_PREFIX + Pattern.quote(imageIdOrName) + PATTERN_IMAGE_SUFFIX);
|
||||
return new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
for (String tag : input.repoTags()) {
|
||||
if (imgPattern.matcher(tag).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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.config;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.name.Names;
|
||||
import com.google.inject.util.Modules;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.handlers.DockerErrorHandler;
|
||||
import org.jclouds.docker.suppliers.DockerUntrustedSSLContextSupplier;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
import org.jclouds.http.okhttp.OkHttpClientSupplier;
|
||||
import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.config.HttpApiModule;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
/**
|
||||
* Configures the Docker connection.
|
||||
*/
|
||||
@ConfiguresHttpApi
|
||||
@ConfiguresHttpCommandExecutorService
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* This configures SSL certificate authentication when the Docker daemon is set to use an encrypted TCP socket
|
||||
*/
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
install(Modules.override(new OkHttpCommandExecutorServiceModule()).with(new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(new TypeLiteral<Supplier<SSLContext>>() {}).annotatedWith(Names.named("untrusted")).to(DockerUntrustedSSLContextSupplier.class);
|
||||
}
|
||||
}));
|
||||
bind(OkHttpClientSupplier.class).to(DockerOkHttpClientSupplier.class);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.config;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.docker.suppliers.DockerSSLContextSupplier;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.okhttp.OkHttpClientSupplier;
|
||||
import org.jclouds.location.Provider;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.squareup.okhttp.ConnectionSpec;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.TlsVersion;
|
||||
|
||||
@Singleton
|
||||
public class DockerOkHttpClientSupplier implements OkHttpClientSupplier {
|
||||
|
||||
private final DockerSSLContextSupplier dockerSSLContextSupplier;
|
||||
private final Supplier<Credentials> creds;
|
||||
|
||||
@Inject
|
||||
DockerOkHttpClientSupplier(DockerSSLContextSupplier dockerSSLContextSupplier, @Provider Supplier<Credentials> creds) {
|
||||
this.dockerSSLContextSupplier = dockerSSLContextSupplier;
|
||||
this.creds = creds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OkHttpClient get() {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
ConnectionSpec tlsSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
|
||||
.tlsVersions(TlsVersion.TLS_1_0, TlsVersion.TLS_1_1, TlsVersion.TLS_1_2)
|
||||
.build();
|
||||
ConnectionSpec cleartextSpec = new ConnectionSpec.Builder(ConnectionSpec.CLEARTEXT)
|
||||
.build();
|
||||
client.setConnectionSpecs(ImmutableList.of(tlsSpec, cleartextSpec));
|
||||
// check if identity and credential are files, to set up sslContext
|
||||
if (new File(creds.get().identity).isFile() && new File(creds.get().credential).isFile()) {
|
||||
client.setSslSocketFactory(dockerSSLContextSupplier.get().getSocketFactory());
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
package org.jclouds.docker.config;
|
||||
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
public class DockerParserModule extends AbstractModule {
|
||||
|
||||
@Override protected void configure() {
|
||||
bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* 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 static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyWithNullOf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.docker.domain.HostConfig.Builder;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Config {
|
||||
@Nullable public abstract String hostname();
|
||||
|
||||
@Nullable public abstract String domainname();
|
||||
|
||||
@Nullable public abstract String user();
|
||||
|
||||
public abstract int memory();
|
||||
|
||||
public abstract int memorySwap();
|
||||
|
||||
public abstract int cpuShares();
|
||||
|
||||
public abstract boolean attachStdin();
|
||||
|
||||
public abstract boolean attachStdout();
|
||||
|
||||
public abstract boolean attachStderr();
|
||||
|
||||
public abstract boolean tty();
|
||||
|
||||
public abstract boolean openStdin();
|
||||
|
||||
public abstract boolean stdinOnce();
|
||||
|
||||
@Nullable public abstract List<String> env();
|
||||
|
||||
@Nullable public abstract List<String> cmd();
|
||||
|
||||
@Nullable public abstract List<String> entrypoint();
|
||||
|
||||
public abstract String image();
|
||||
|
||||
@Nullable public abstract Map<String, ?> volumes();
|
||||
|
||||
@Nullable public abstract String workingDir();
|
||||
|
||||
public abstract boolean networkDisabled();
|
||||
|
||||
public abstract Map<String, ?> exposedPorts();
|
||||
|
||||
public abstract List<String> securityOpts();
|
||||
|
||||
@Nullable public abstract HostConfig hostConfig();
|
||||
|
||||
Config() {
|
||||
}
|
||||
|
||||
@SerializedNames(
|
||||
{
|
||||
"Hostname", "Domainname", "User", "Memory", "MemorySwap", "CpuShares", "AttachStdin", "AttachStdout",
|
||||
"AttachStderr", "Tty", "OpenStdin", "StdinOnce", "Env", "Cmd", "Entrypoint", "Image", "Volumes",
|
||||
"WorkingDir", "NetworkDisabled", "ExposedPorts", "SecurityOpts", "HostConfig"
|
||||
})
|
||||
public static Config create(String hostname, String domainname, String user, int memory, int memorySwap,
|
||||
int cpuShares, boolean attachStdin, boolean attachStdout, boolean attachStderr, boolean tty,
|
||||
boolean openStdin, boolean stdinOnce, List<String> env, List<String> cmd, List<String> entrypoint,
|
||||
String image, Map<String, ?> volumes, String workingDir, boolean networkDisabled,
|
||||
Map<String, ?> exposedPorts, List<String> securityOpts, HostConfig hostConfig) {
|
||||
return new AutoValue_Config(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin,
|
||||
attachStdout, attachStderr, tty, openStdin, stdinOnce, copyWithNullOf(env), copyWithNullOf(cmd),
|
||||
copyWithNullOf(entrypoint), image, copyWithNullOf(volumes), workingDir, networkDisabled,
|
||||
copyOf(exposedPorts), copyOf(securityOpts), hostConfig);
|
||||
}
|
||||
|
||||
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 boolean tty;
|
||||
private boolean openStdin;
|
||||
private boolean stdinOnce;
|
||||
private List<String> env;
|
||||
private List<String> cmd;
|
||||
private List<String> entrypoint;
|
||||
private String image;
|
||||
private Map<String, ?> volumes;
|
||||
private String workingDir;
|
||||
private boolean networkDisabled;
|
||||
private Map<String, ?> exposedPorts = Maps.newHashMap();
|
||||
private List<String> securityOpts = Lists.newArrayList();
|
||||
private HostConfig hostConfig;
|
||||
|
||||
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(Integer memory) {
|
||||
if (memory != null) {
|
||||
this.memory = memory;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder memorySwap(Integer memorySwap) {
|
||||
if (memorySwap != null) {
|
||||
this.memorySwap = memorySwap;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder cpuShares(Integer cpuShares) {
|
||||
if (cpuShares != null) {
|
||||
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 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 = cmd;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder entrypoint(List<String> entrypoint) {
|
||||
this.entrypoint = entrypoint;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder image(String image) {
|
||||
this.image = checkNotNull(image, "image");
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder volumes(Map<String, ?> volumes) {
|
||||
this.volumes = volumes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder workingDir(String workingDir) {
|
||||
this.workingDir = workingDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder networkDisabled(boolean networkDisabled) {
|
||||
this.networkDisabled = networkDisabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder exposedPorts(Map<String, ?> exposedPorts) {
|
||||
this.exposedPorts = exposedPorts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder securityOpts(List<String> securityOpts) {
|
||||
this.securityOpts = securityOpts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hostConfig(HostConfig hostConfig) {
|
||||
this.hostConfig = hostConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Config build() {
|
||||
return Config.create(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
|
||||
attachStderr, tty, openStdin, stdinOnce, env, cmd, entrypoint, image, volumes, workingDir,
|
||||
networkDisabled, exposedPorts, securityOpts, hostConfig);
|
||||
}
|
||||
|
||||
public Builder fromConfig(Config in) {
|
||||
return hostname(in.hostname()).domainname(in.domainname()).user(in.user()).memory(in.memory())
|
||||
.memorySwap(in.memorySwap()).cpuShares(in.cpuShares()).attachStdin(in.attachStdin())
|
||||
.attachStdout(in.attachStdout()).attachStderr(in.attachStderr()).tty(in.tty())
|
||||
.openStdin(in.openStdin()).stdinOnce(in.stdinOnce()).env(in.env()).cmd(in.cmd())
|
||||
.entrypoint(in.entrypoint()).image(in.image()).volumes(in.volumes()).workingDir(in.workingDir())
|
||||
.networkDisabled(in.networkDisabled()).exposedPorts(in.exposedPorts())
|
||||
.securityOpts(in.securityOpts()).hostConfig(in.hostConfig());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Container {
|
||||
public abstract String id();
|
||||
|
||||
@Nullable public abstract Date created();
|
||||
|
||||
@Nullable public abstract String path();
|
||||
|
||||
@Nullable public abstract String name();
|
||||
|
||||
public abstract List<String> args();
|
||||
|
||||
@Nullable public abstract Config config();
|
||||
|
||||
@Nullable public abstract State state();
|
||||
|
||||
@Nullable public abstract String image();
|
||||
|
||||
@Nullable public abstract NetworkSettings networkSettings();
|
||||
|
||||
@Nullable public abstract String sysInitPath();
|
||||
|
||||
@Nullable public abstract String resolvConfPath();
|
||||
|
||||
public abstract Map<String, String> volumes();
|
||||
|
||||
@Nullable public abstract HostConfig hostConfig();
|
||||
|
||||
@Nullable public abstract String driver();
|
||||
|
||||
@Nullable public abstract String execDriver();
|
||||
|
||||
public abstract Map<String, Boolean> volumesRW();
|
||||
|
||||
@Nullable public abstract String command();
|
||||
|
||||
@Nullable public abstract String status();
|
||||
|
||||
public abstract List<Port> ports();
|
||||
|
||||
@Nullable public abstract String hostnamePath();
|
||||
|
||||
@Nullable public abstract String hostsPath();
|
||||
|
||||
@Nullable public abstract String mountLabel();
|
||||
|
||||
@Nullable public abstract String processLabel();
|
||||
|
||||
public abstract Optional<Node> node();
|
||||
|
||||
Container() {
|
||||
}
|
||||
|
||||
@SerializedNames(
|
||||
{
|
||||
"Id", "Created", "Path", "Name", "Args", "Config", "State", "Image", "NetworkSettings", "SysInitPath",
|
||||
"ResolvConfPath", "Volumes", "HostConfig", "Driver", "ExecDriver", "VolumesRW", "Command", "Status",
|
||||
"Ports", "HostnamePath", "HostsPath", "MountLabel", "ProcessLabel", "Node"
|
||||
})
|
||||
public static Container create(String id, Date created, String path, String name, List<String> args, Config config,
|
||||
State state, String image, NetworkSettings networkSettings, String sysInitPath,
|
||||
String resolvConfPath, Map<String, String> volumes, HostConfig hostConfig,
|
||||
String driver, String execDriver, Map<String, Boolean> volumesRW, String command,
|
||||
String status, List<Port> ports, String hostnamePath, String hostsPath,
|
||||
String mountLabel, String processLabel, Optional<Node> node) {
|
||||
return new AutoValue_Container(id, created, path, name, copyOf(args), config, state, image, networkSettings,
|
||||
sysInitPath, resolvConfPath, copyOf(volumes), hostConfig, driver, execDriver, copyOf(volumesRW), command,
|
||||
status, copyOf(ports), hostnamePath, hostsPath, mountLabel, processLabel, node);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromContainer(this);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private String id;
|
||||
private Date created;
|
||||
private String path;
|
||||
private String name;
|
||||
private List<String> args;
|
||||
private Config config;
|
||||
private State state;
|
||||
private String image;
|
||||
private NetworkSettings networkSettings;
|
||||
private String sysInitPath;
|
||||
private String resolvConfPath;
|
||||
private Map<String, String> volumes = ImmutableMap.of();
|
||||
private HostConfig hostConfig;
|
||||
private String driver;
|
||||
private String execDriver;
|
||||
private Map<String, Boolean> volumesRW = ImmutableMap.of();
|
||||
private String command;
|
||||
private String status;
|
||||
private List<Port> ports = ImmutableList.of();
|
||||
private String hostnamePath;
|
||||
private String hostsPath;
|
||||
private String mountLabel;
|
||||
private String processLabel;
|
||||
private Optional<Node> node = Optional.absent();
|
||||
|
||||
public Builder id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder created(Date created) {
|
||||
this.created = created;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder path(String path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder args(List<String> args) {
|
||||
this.args = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder config(Config config) {
|
||||
this.config = config;
|
||||
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 sysInitPath(String sysInitPath) {
|
||||
this.sysInitPath = sysInitPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resolvConfPath(String resolvConfPath) {
|
||||
this.resolvConfPath = resolvConfPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder volumes(Map<String, String> volumes) {
|
||||
this.volumes = volumes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hostConfig(HostConfig hostConfig) {
|
||||
this.hostConfig = hostConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder driver(String driver) {
|
||||
this.driver = driver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder execDriver(String execDriver) {
|
||||
this.execDriver = execDriver;
|
||||
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 ports(List<Port> ports) {
|
||||
this.ports = ports;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hostnamePath(String hostnamePath) {
|
||||
this.hostnamePath = hostnamePath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hostsPath(String hostsPath) {
|
||||
this.hostsPath = hostsPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mountLabel(String mountLabel) {
|
||||
this.mountLabel = mountLabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processLabel(String processLabel) {
|
||||
this.processLabel = processLabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder node(Node node) {
|
||||
this.node = Optional.fromNullable(node);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Container build() {
|
||||
return Container.create(id, created, path, name, args, config, state, image, networkSettings,
|
||||
sysInitPath, resolvConfPath, volumes, hostConfig, driver, execDriver, volumesRW, command, status,
|
||||
ports, hostnamePath, hostsPath, mountLabel, processLabel, node);
|
||||
}
|
||||
|
||||
public Builder fromContainer(Container in) {
|
||||
return this.id(in.id()).name(in.name()).created(in.created()).path(in.path()).args(in.args())
|
||||
.config(in.config()).state(in.state()).image(in.image()).networkSettings(in.networkSettings())
|
||||
.sysInitPath(in.sysInitPath()).resolvConfPath(in.resolvConfPath()).driver(in.driver())
|
||||
.execDriver(in.execDriver()).volumes(in.volumes()).hostConfig(in.hostConfig()).volumesRW(in.volumesRW())
|
||||
.command(in.command()).status(in.status()).ports(in.ports()).hostnamePath(in.hostnamePath())
|
||||
.hostsPath(in.hostsPath()).mountLabel(in.mountLabel()).processLabel(in.processLabel()).node(in.node().orNull());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
// TODO it may be redundant (we already have Container value class)
|
||||
@AutoValue
|
||||
public abstract class ContainerSummary {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
public abstract List<String> names();
|
||||
|
||||
public abstract String created();
|
||||
|
||||
public abstract String image();
|
||||
|
||||
public abstract String command();
|
||||
|
||||
public abstract List<Port> ports();
|
||||
|
||||
public abstract String status();
|
||||
|
||||
ContainerSummary() {
|
||||
}
|
||||
|
||||
@SerializedNames({"Id", "Names", "Created", "Image", "Command", "Ports", "Status"})
|
||||
public static ContainerSummary create(String id, List<String> names, String created, String image, String command, List<Port> ports, String status) {
|
||||
return new AutoValue_ContainerSummary(id, copyOf(names), created, image, command, copyOf(ports), status);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Represents a response from Exec Create call (<code>POST /containers/(id)/exec</code>).
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class Exec {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
@SerializedNames({ "Id"})
|
||||
public static Exec create(String id) {
|
||||
return new AutoValue_Exec(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Json Parameters (some of them) of Exec Create call.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class ExecCreateParams {
|
||||
|
||||
public abstract boolean attachStdout();
|
||||
|
||||
public abstract boolean attachStderr();
|
||||
|
||||
public abstract List<String> cmd();
|
||||
|
||||
@SerializedNames({ "AttachStdout", "AttachStderr", "Cmd" })
|
||||
private static ExecCreateParams create(boolean attachStdout, boolean attachStderr, List<String> cmd) {
|
||||
return builder().attachStdout(attachStdout).attachStderr(attachStderr).cmd(cmd).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates builder for {@link ExecCreateParams}, it sets
|
||||
* {@link #attachStderr()} and {@link #attachStdout()} to true as a default.
|
||||
*
|
||||
* @return new {@link ExecCreateParams.Builder} instance
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new AutoValue_ExecCreateParams.Builder().attachStderr(true).attachStdout(true);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder attachStdout(boolean b);
|
||||
|
||||
public abstract Builder attachStderr(boolean b);
|
||||
|
||||
public abstract Builder cmd(List<String> cmd);
|
||||
|
||||
abstract List<String> cmd();
|
||||
|
||||
abstract ExecCreateParams autoBuild();
|
||||
|
||||
public ExecCreateParams build() {
|
||||
cmd(copyOf(cmd()));
|
||||
return autoBuild();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Represents a response (part of it) from Exec Inspect call (
|
||||
* <code>GET /exec/(id)/json</code>).
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class ExecInspect {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
public abstract boolean running();
|
||||
|
||||
public abstract int exitCode();
|
||||
|
||||
@SerializedNames({ "ID", "Running", "ExitCode"})
|
||||
public static ExecInspect create(String id, boolean running, int exitCode) {
|
||||
return new AutoValue_ExecInspect(id, running, exitCode);
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Json Parameter(s) (some of them) of Exec Start call.
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class ExecStartParams {
|
||||
|
||||
public abstract boolean detach();
|
||||
|
||||
@SerializedNames({ "Detach" })
|
||||
public static ExecStartParams create(boolean detach) {
|
||||
return builder().detach(detach).build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_ExecStartParams.Builder().detach(false);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder detach(boolean b);
|
||||
|
||||
public abstract ExecStartParams build();
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class ExposedPorts {
|
||||
public abstract String portAndProtocol();
|
||||
|
||||
public abstract List<String> hostPorts();
|
||||
|
||||
ExposedPorts() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "PortAndProtocol", "HostPorts" })
|
||||
public static ExposedPorts create(String portAndProtocol, List<String> hostPorts) {
|
||||
return new AutoValue_ExposedPorts(portAndProtocol, copyOf(hostPorts));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyWithNullOf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
@AutoValue
|
||||
public abstract class HostConfig {
|
||||
@Nullable public abstract String containerIDFile();
|
||||
|
||||
@Nullable public abstract List<String> binds();
|
||||
|
||||
public abstract List<Map<String, String>> lxcConf();
|
||||
|
||||
public abstract boolean privileged();
|
||||
|
||||
@Nullable public abstract List<String> dns();
|
||||
|
||||
@Nullable public abstract List<String> dnsSearch();
|
||||
|
||||
public abstract Map<String, List<Map<String, String>>> portBindings();
|
||||
|
||||
@Nullable public abstract List<String> links();
|
||||
|
||||
@Nullable public abstract List<String> extraHosts();
|
||||
|
||||
public abstract boolean publishAllPorts();
|
||||
|
||||
@Nullable public abstract List<String> volumesFrom();
|
||||
|
||||
@Nullable public abstract String networkMode();
|
||||
|
||||
@Nullable public abstract List<String> securityOpt();
|
||||
|
||||
@Nullable public abstract List<String> capAdd();
|
||||
|
||||
@Nullable public abstract List<String> capDrop();
|
||||
|
||||
public abstract Map<String, String> restartPolicy();
|
||||
|
||||
|
||||
|
||||
HostConfig() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "ContainerIDFile", "Binds", "LxcConf", "Privileged", "Dns", "DnsSearch", "PortBindings",
|
||||
"Links", "ExtraHosts", "PublishAllPorts", "VolumesFrom", "NetworkMode", "SecurityOpt",
|
||||
"CapAdd", "CapDrop", "RestartPolicy" })
|
||||
public static HostConfig create(String containerIDFile, List<String> binds, List<Map<String, String>> lxcConf,
|
||||
boolean privileged, List<String> dns, List<String> dnsSearch, Map<String, List<Map<String, String>>> portBindings,
|
||||
List<String> links, List<String> extraHosts, boolean publishAllPorts, List<String> volumesFrom, String networkMode,
|
||||
List<String> securityOpt, List<String> capAdd, List<String> capDrop, Map<String, String> restartPolicy) {
|
||||
return new AutoValue_HostConfig(containerIDFile, copyWithNullOf(binds), copyOf(lxcConf), privileged, copyWithNullOf(dns), copyWithNullOf(dnsSearch),
|
||||
copyOf(portBindings), copyWithNullOf(links), copyWithNullOf(extraHosts), publishAllPorts, copyWithNullOf(volumesFrom), networkMode,
|
||||
copyOf(securityOpt), copyWithNullOf(capAdd), copyWithNullOf(capDrop), copyOf(restartPolicy));
|
||||
}
|
||||
|
||||
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;
|
||||
private List<Map<String, String>> lxcConf = Lists.newArrayList();
|
||||
private boolean privileged;
|
||||
private List<String> dns;
|
||||
private List<String> dnsSearch;
|
||||
private Map<String, List<Map<String, String>>> portBindings = Maps.newLinkedHashMap();
|
||||
private List<String> links;
|
||||
private List<String> extraHosts;
|
||||
private boolean publishAllPorts;
|
||||
private List<String> volumesFrom;
|
||||
private String networkMode;
|
||||
private List<String> securityOpt = Lists.newArrayList();
|
||||
private List<String> capAdd;
|
||||
private List<String> capDrop;
|
||||
private Map<String, String> restartPolicy = Maps.newHashMap();
|
||||
|
||||
public Builder containerIDFile(String containerIDFile) {
|
||||
this.containerIDFile = containerIDFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder binds(List<String> binds) {
|
||||
this.binds = binds;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lxcConf(List<Map<String, String>> lxcConf) {
|
||||
this.lxcConf = lxcConf;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder privileged(boolean privileged) {
|
||||
this.privileged = privileged;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder dns(List<String> dns) {
|
||||
this.dns = dns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder dnsSearch(List<String> dnsSearch) {
|
||||
this.dnsSearch = dnsSearch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder links(List<String> links) {
|
||||
this.links = links;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder extraHosts(List<String> extraHosts) {
|
||||
this.extraHosts = extraHosts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder portBindings(Map<String, List<Map<String, String>>> portBindings) {
|
||||
this.portBindings = portBindings;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder publishAllPorts(boolean publishAllPorts) {
|
||||
this.publishAllPorts = publishAllPorts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder volumesFrom(List<String> volumesFrom) {
|
||||
this.volumesFrom = volumesFrom;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder networkMode(String networkMode) {
|
||||
this.networkMode = networkMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder securityOpt(List<String> securityOpt) {
|
||||
this.securityOpt = securityOpt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder capAdd(List<String> capAdd) {
|
||||
this.capAdd = capAdd;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder capDrop(List<String> capDrop) {
|
||||
this.capDrop = capDrop;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder restartPolicy(Map<String, String> restartPolicy) {
|
||||
this.restartPolicy = restartPolicy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HostConfig build() {
|
||||
return HostConfig.create(containerIDFile, binds, lxcConf, privileged, dns, dnsSearch, portBindings, links,
|
||||
extraHosts, publishAllPorts, volumesFrom, networkMode, securityOpt, capAdd, capDrop, restartPolicy);
|
||||
}
|
||||
|
||||
public Builder fromHostConfig(HostConfig in) {
|
||||
return this.containerIDFile(in.containerIDFile()).binds(in.binds()).lxcConf(in.lxcConf())
|
||||
.privileged(in.privileged()).dns(in.dns()).dnsSearch(in.dnsSearch()).links(in.links())
|
||||
.extraHosts(in.extraHosts()).portBindings(in.portBindings()).publishAllPorts(in.publishAllPorts())
|
||||
.volumesFrom(in.volumesFrom()).networkMode(in.networkMode()).securityOpt(in.securityOpt())
|
||||
.capAdd(in.capAdd()).capDrop(in.capDrop()).restartPolicy(in.restartPolicy());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
/**
|
||||
* Represents a response from Docker "Inspect an image" call (<code>GET /images/(name)/json</code>).
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class Image {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
@Nullable public abstract String author();
|
||||
|
||||
@Nullable public abstract String comment();
|
||||
|
||||
@Nullable public abstract Config config();
|
||||
|
||||
@Nullable public abstract Config containerConfig();
|
||||
|
||||
public abstract String parent();
|
||||
|
||||
public abstract Date created();
|
||||
|
||||
public abstract String container();
|
||||
|
||||
public abstract String dockerVersion();
|
||||
|
||||
public abstract String architecture();
|
||||
|
||||
public abstract String os();
|
||||
|
||||
public abstract long size();
|
||||
|
||||
public abstract long virtualSize();
|
||||
|
||||
/**
|
||||
* Tags of the image. The value is <code>null</code> when the instance comes
|
||||
* from {@link org.jclouds.docker.features.ImageApi#inspectImage(String)}.
|
||||
* Other methods can populate the content (e.g.
|
||||
* {@link org.jclouds.docker.compute.strategy.DockerComputeServiceAdapter#listImages()}
|
||||
* call.
|
||||
* <p>
|
||||
* The tags are in form "ubuntu:12.10", "docker.io/busybox:1.23.2", ...
|
||||
* </p>
|
||||
* @return list of tags or <code>null</code>
|
||||
*/
|
||||
@Nullable public abstract List<String> repoTags();
|
||||
|
||||
Image() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "Id", "Author", "Comment", "Config", "ContainerConfig", "Parent", "Created",
|
||||
"Container", "DockerVersion", "Architecture", "Os", "Size", "VirtualSize", "RepoTags" })
|
||||
public static Image create(String id, String author, String comment, Config config, Config containerConfig, String parent, Date created, String container, String dockerVersion, String architecture, String os, long size, long virtualSize, List<String> repoTags) {
|
||||
return new AutoValue_Image(id, author, comment, config, containerConfig, parent, created, container,
|
||||
dockerVersion, architecture, os, size, virtualSize, copyOf(repoTags));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class ImageHistory {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
public abstract long created();
|
||||
|
||||
public abstract String createdBy();
|
||||
|
||||
@Nullable public abstract List<String> tags();
|
||||
|
||||
public abstract long size();
|
||||
|
||||
public abstract String comment();
|
||||
|
||||
|
||||
ImageHistory() {
|
||||
}
|
||||
|
||||
@SerializedNames({"Id", "Created", "CreatedBy", "Tags", "Size", "Comment"})
|
||||
public static ImageHistory create(String id, long created, String createdBy, List<String> tags, long size, String comment) {
|
||||
return new AutoValue_ImageHistory(id, created, createdBy, copyOf(tags), size, comment);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
// TODO it may be redundant (we already have Image value class)
|
||||
@AutoValue
|
||||
public abstract class ImageSummary {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
public abstract long created();
|
||||
|
||||
public abstract String parentId();
|
||||
|
||||
public abstract int size();
|
||||
|
||||
public abstract int virtualSize();
|
||||
|
||||
public abstract List<String> repoTags();
|
||||
|
||||
ImageSummary() {
|
||||
}
|
||||
|
||||
@SerializedNames({"Id", "Created", "ParentId", "Size", "VirtualSize", "RepoTags"})
|
||||
public static ImageSummary create(String id, long created, String parentId, int size, int virtualSize,
|
||||
List<String> repoTags) {
|
||||
return new AutoValue_ImageSummary(id, created, parentId, size, virtualSize, copyOf(repoTags));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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 java.util.List;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Info {
|
||||
|
||||
public abstract int containers();
|
||||
|
||||
public abstract boolean debug();
|
||||
|
||||
public abstract String driver();
|
||||
|
||||
public abstract List<List<String>> driverStatus();
|
||||
|
||||
public abstract String executionDriver();
|
||||
|
||||
public abstract boolean iPv4Forwarding();
|
||||
|
||||
public abstract int images();
|
||||
|
||||
public abstract String indexServerAddress();
|
||||
|
||||
@Nullable public abstract String initPath();
|
||||
|
||||
@Nullable public abstract String initSha1();
|
||||
|
||||
public abstract String kernelVersion();
|
||||
|
||||
public abstract boolean memoryLimit();
|
||||
|
||||
public abstract int nEventsListener();
|
||||
|
||||
public abstract int nFd();
|
||||
|
||||
public abstract int nGoroutines();
|
||||
|
||||
public abstract String operatingSystem();
|
||||
|
||||
public abstract boolean swapLimit();
|
||||
|
||||
public abstract String dockerRootDir();
|
||||
|
||||
/**
|
||||
* @return a list of daemon labels
|
||||
*/
|
||||
@Nullable public abstract List<String> labels();
|
||||
|
||||
/**
|
||||
* @return total memory available
|
||||
*/
|
||||
public abstract long memTotal();
|
||||
|
||||
/**
|
||||
* @return the number of CPUs available on the machine
|
||||
*/
|
||||
public abstract int ncpu();
|
||||
|
||||
/**
|
||||
* @return a unique ID identifying the daemon
|
||||
*/
|
||||
public abstract String id();
|
||||
|
||||
/**
|
||||
* @return a user-friendly name describing the running Docker daemon
|
||||
*/
|
||||
public abstract String name();
|
||||
|
||||
Info() {
|
||||
}
|
||||
|
||||
@SerializedNames({
|
||||
"Containers", "Debug", "Driver", "DriverStatus", "ExecutionDriver", "IPv4Forwarding", "Images",
|
||||
"IndexServerAddress", "InitPath", "InitSha1", "KernelVersion", "MemoryLimit", "NEventsListener",
|
||||
"NFd", "NGoroutines", "OperatingSystem", "SwapLimit", "DockerRootDir", "Labels", "MemTotal", "NCPU",
|
||||
"ID", "Name"
|
||||
})
|
||||
public static Info create(int containers, boolean debug, String driver, List<List<String>> driverStatus,
|
||||
String executionDriver, boolean iPv4Forwarding, int images, String indexServerAddress,
|
||||
String initPath, String initSha1, String kernelVersion, boolean memoryLimit,
|
||||
int nEventsListener, int nFd, int nGoroutines, String operatingSystem, boolean swapLimit,
|
||||
String dockerRootDir, List<String> labels, long memTotal, int ncpu, String id, String name) {
|
||||
return new AutoValue_Info(containers, debug, driver, driverStatus, executionDriver, iPv4Forwarding, images,
|
||||
indexServerAddress, initPath, initSha1, kernelVersion, memoryLimit, nEventsListener, nFd, nGoroutines,
|
||||
operatingSystem, swapLimit, dockerRootDir, labels, memTotal, ncpu, id, name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyWithNullOf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Network {
|
||||
|
||||
@AutoValue
|
||||
public abstract static class IPAM {
|
||||
|
||||
IPAM() { }
|
||||
|
||||
@Nullable public abstract String driver();
|
||||
|
||||
public abstract List<Config> config();
|
||||
|
||||
@SerializedNames({"Driver", "Config"})
|
||||
public static IPAM create(@Nullable String driver, List<Config> config) {
|
||||
return builder()
|
||||
.driver(driver)
|
||||
.config(config)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_Network_IPAM.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder driver(@Nullable String driver);
|
||||
|
||||
public abstract Builder config(List<Config> config);
|
||||
|
||||
abstract List<Config> config();
|
||||
|
||||
abstract IPAM autoBuild();
|
||||
|
||||
public IPAM build() {
|
||||
return config(copyOf(config()))
|
||||
.autoBuild();
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
public abstract static class Config {
|
||||
|
||||
Config() { }
|
||||
|
||||
public abstract String subnet();
|
||||
|
||||
@Nullable public abstract String ipRange();
|
||||
|
||||
@Nullable public abstract String gateway();
|
||||
|
||||
@SerializedNames({"Subnet", "IPRange", "Gateway"})
|
||||
public static Config create(String subnet, @Nullable String ipRange, @Nullable String gateway) {
|
||||
return builder()
|
||||
.subnet(subnet)
|
||||
.ipRange(ipRange)
|
||||
.gateway(gateway)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_Network_IPAM_Config.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder subnet(String subnet);
|
||||
|
||||
public abstract Builder ipRange(@Nullable String ipRange);
|
||||
|
||||
public abstract Builder gateway(@Nullable String gateway);
|
||||
|
||||
abstract Config build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
public abstract static class Details {
|
||||
|
||||
Details() { }
|
||||
|
||||
public abstract String endpoint();
|
||||
|
||||
public abstract String macAddress();
|
||||
|
||||
public abstract String ipv4address();
|
||||
|
||||
public abstract String ipv6address();
|
||||
|
||||
@SerializedNames({ "EndpointID", "MacAddress", "IPv4Address", "IPv6Address" })
|
||||
public static Details create(String endpoint, String macAddress, String ipv4address, String ipv6address) {
|
||||
return builder()
|
||||
.endpoint(endpoint)
|
||||
.macAddress(macAddress)
|
||||
.ipv4address(ipv4address)
|
||||
.ipv6address(ipv6address)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_Network_Details.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder endpoint(String endpoint);
|
||||
|
||||
public abstract Builder macAddress(String macAddress);
|
||||
|
||||
public abstract Builder ipv4address(String ipv4address);
|
||||
|
||||
public abstract Builder ipv6address(String ipv6address);
|
||||
|
||||
abstract Details build();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable public abstract String name();
|
||||
|
||||
@Nullable public abstract String id();
|
||||
|
||||
@Nullable public abstract String scope();
|
||||
|
||||
@Nullable public abstract String driver();
|
||||
|
||||
@Nullable public abstract IPAM ipam();
|
||||
|
||||
@Nullable public abstract Map<String, Details> containers();
|
||||
|
||||
@Nullable public abstract Map<String, String> options();
|
||||
|
||||
Network() { }
|
||||
|
||||
@SerializedNames({ "Name", "Id", "Scope", "Driver", "IPAM", "Containers", "Options" })
|
||||
public static Network create(@Nullable String name, @Nullable String id, @Nullable String scope,
|
||||
@Nullable String driver, @Nullable IPAM ipam, @Nullable Map<String, Details> containers,
|
||||
@Nullable Map<String, String> options) {
|
||||
return builder()
|
||||
.name(name)
|
||||
.id(id)
|
||||
.scope(scope)
|
||||
.driver(driver)
|
||||
.ipam(ipam)
|
||||
.containers(containers)
|
||||
.options(options)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_Network.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
|
||||
public abstract Builder name(@Nullable String name);
|
||||
|
||||
public abstract Builder id(@Nullable String id);
|
||||
|
||||
public abstract Builder scope(@Nullable String scope);
|
||||
|
||||
public abstract Builder driver(@Nullable String driver);
|
||||
|
||||
public abstract Builder ipam(@Nullable IPAM ipam);
|
||||
|
||||
public abstract Builder containers(@Nullable Map<String, Details> containers);
|
||||
|
||||
public abstract Builder options(@Nullable Map<String, String> options);
|
||||
|
||||
abstract Map<String, Details> containers();
|
||||
|
||||
abstract Map<String, String> options();
|
||||
|
||||
abstract Network autoBuild();
|
||||
|
||||
public Network build() {
|
||||
return containers(copyWithNullOf(containers()))
|
||||
.options(copyOf(options()))
|
||||
.autoBuild();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.docker.internal.NullSafeCopies;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@AutoValue
|
||||
public abstract class NetworkSettings {
|
||||
|
||||
@AutoValue
|
||||
public abstract static class Details {
|
||||
|
||||
Details() {} // For AutoValue only!
|
||||
|
||||
public abstract String endpoint();
|
||||
|
||||
public abstract String gateway();
|
||||
|
||||
public abstract String ipAddress();
|
||||
|
||||
public abstract int ipPrefixLen();
|
||||
|
||||
public abstract String ipv6Gateway();
|
||||
|
||||
public abstract String globalIPv6Address();
|
||||
|
||||
public abstract int globalIPv6PrefixLen();
|
||||
|
||||
public abstract String macAddress();
|
||||
|
||||
@SerializedNames({ "EndpointID", "Gateway", "IPAddress", "IPPrefixLen", "IPv6Gateway", "GlobalIPv6Address", "GlobalIPv6PrefixLen", "MacAddress" })
|
||||
public static Details create(String endpointId, String gateway, String ipAddress, int ipPrefixLen, String ipv6Gateway, String globalIPv6Address,
|
||||
int globalIPv6PrefixLen, String macAddress) {
|
||||
return builder().endpoint(endpointId).gateway(gateway).ipAddress(ipAddress).ipPrefixLen(ipPrefixLen)
|
||||
.ipv6Gateway(ipv6Gateway).globalIPv6Address(globalIPv6Address)
|
||||
.globalIPv6PrefixLen(globalIPv6PrefixLen).macAddress(macAddress)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return new AutoValue_NetworkSettings_Details.Builder(this);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new AutoValue_NetworkSettings_Details.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
public abstract Builder endpoint(String value);
|
||||
public abstract Builder gateway(String value);
|
||||
public abstract Builder ipAddress(String value);
|
||||
public abstract Builder ipPrefixLen(int value);
|
||||
public abstract Builder ipv6Gateway(String value);
|
||||
public abstract Builder globalIPv6Address(String value);
|
||||
public abstract Builder globalIPv6PrefixLen(int value);
|
||||
public abstract Builder macAddress(String value);
|
||||
|
||||
public abstract Details build();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract String bridge();
|
||||
|
||||
@Nullable public abstract String sandboxId();
|
||||
|
||||
public abstract boolean hairpinMode();
|
||||
|
||||
@Nullable public abstract String linkLocalIPv6Address();
|
||||
|
||||
public abstract int linkLocalIPv6PrefixLen();
|
||||
|
||||
@Nullable public abstract Map<String, List<Map<String, String>>> ports();
|
||||
|
||||
@Nullable public abstract String sandboxKey();
|
||||
|
||||
public abstract List<String> secondaryIPAddresses();
|
||||
|
||||
public abstract List<String> secondaryIPv6Addresses();
|
||||
|
||||
@Nullable public abstract String endpointId();
|
||||
|
||||
public abstract String gateway();
|
||||
|
||||
@Nullable public abstract String globalIPv6Address();
|
||||
|
||||
public abstract int globalIPv6PrefixLen();
|
||||
|
||||
public abstract String ipAddress();
|
||||
|
||||
public abstract int ipPrefixLen();
|
||||
|
||||
@Nullable public abstract String ipv6Gateway();
|
||||
|
||||
@Nullable public abstract String macAddress();
|
||||
|
||||
public abstract Map<String, Details> networks();
|
||||
|
||||
@Nullable public abstract String portMapping();
|
||||
|
||||
NetworkSettings() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "Bridge", "SandboxID", "HairpinMode", "LinkLocalIPv6Address",
|
||||
"LinkLocalIPv6PrefixLen", "Ports", "SandboxKey", "SecondaryIPAddresses",
|
||||
"SecondaryIPv6Addresses", "EndpointID", "Gateway", "GlobalIPv6Address",
|
||||
"GlobalIPv6PrefixLen", "IPAddress", "IPPrefixLen", "IPv6Gateway",
|
||||
"MacAddress", "Networks", "PortMapping" })
|
||||
public static NetworkSettings create(String bridge, String sandboxId, boolean hairpinMode, String linkLocalIPv6Address,
|
||||
int linkLocalIPv6PrefixLen, Map<String, List<Map<String, String>>> ports, String sandboxKey, List<String> secondaryIPAddresses,
|
||||
List<String> secondaryIPv6Addresses, String endpointId, String gateway, String globalIPv6Address,
|
||||
int globalIPv6PrefixLen, String ipAddress, int ipPrefixLen, String ipv6Gateway,
|
||||
String macAddress, Map<String, Details> networks, String portMapping) {
|
||||
return new AutoValue_NetworkSettings(
|
||||
bridge, sandboxId, hairpinMode, linkLocalIPv6Address,
|
||||
linkLocalIPv6PrefixLen, ports, sandboxKey, copyOf(secondaryIPAddresses), copyOf(secondaryIPv6Addresses),
|
||||
endpointId, gateway, globalIPv6Address, globalIPv6PrefixLen,
|
||||
ipAddress, ipPrefixLen, ipv6Gateway,
|
||||
macAddress, copyOf(networks), portMapping);
|
||||
}
|
||||
|
||||
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;
|
||||
private String sandboxId;
|
||||
private boolean hairpinMode;
|
||||
private String linkLocalIPv6Address;
|
||||
private int linkLocalIPv6PrefixLen;
|
||||
private String sandboxKey;
|
||||
private List<String> secondaryIPAddresses = Lists.newArrayList();
|
||||
private List<String> secondaryIPv6Addresses = Lists.newArrayList();
|
||||
private String endpointId;
|
||||
private String globalIPv6Address;
|
||||
private int globalIPv6PrefixLen;
|
||||
private String ipv6Gateway;
|
||||
private String macAddress;
|
||||
private Map<String, Details> networks = Maps.newHashMap();
|
||||
|
||||
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 = NullSafeCopies.copyWithNullOf(ports);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder sandboxId(String sandboxId) {
|
||||
this.sandboxId = sandboxId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hairpinMode(boolean hairpinMode) {
|
||||
this.hairpinMode = hairpinMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder linkLocalIPv6Address(String linkLocalIPv6Address) {
|
||||
this.linkLocalIPv6Address = linkLocalIPv6Address;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder linkLocalIPv6PrefixLen(int linkLocalIPv6PrefixLen) {
|
||||
this.linkLocalIPv6PrefixLen = linkLocalIPv6PrefixLen;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder sandboxKey(String sandboxKey) {
|
||||
this.sandboxKey = sandboxKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder secondaryIPAddresses(List<String> secondaryIPAddresses) {
|
||||
this.secondaryIPAddresses = secondaryIPAddresses;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder secondaryIPv6Addresses(List<String> secondaryIPv6Addresses) {
|
||||
this.secondaryIPv6Addresses = secondaryIPv6Addresses;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder endpointId(String endpointId) {
|
||||
this.endpointId = endpointId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder globalIPv6Address(String globalIPv6Address) {
|
||||
this.globalIPv6Address = globalIPv6Address;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder globalIPv6PrefixLen(int globalIPv6PrefixLen) {
|
||||
this.globalIPv6PrefixLen = globalIPv6PrefixLen;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder ipv6Gateway(String ipv6Gateway) {
|
||||
this.ipv6Gateway = ipv6Gateway;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder macAddress(String macAddress) {
|
||||
this.macAddress = macAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder networks(Map<String, Details> networks) {
|
||||
this.networks.putAll(networks);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NetworkSettings build() {
|
||||
return NetworkSettings.create(bridge, sandboxId, hairpinMode, linkLocalIPv6Address, linkLocalIPv6PrefixLen, ports,
|
||||
sandboxKey, secondaryIPAddresses, secondaryIPv6Addresses, endpointId, gateway,
|
||||
globalIPv6Address, globalIPv6PrefixLen, ipAddress, ipPrefixLen, ipv6Gateway, macAddress, networks, portMapping);
|
||||
}
|
||||
|
||||
public Builder fromNetworkSettings(NetworkSettings in) {
|
||||
return this.ipAddress(in.ipAddress()).ipPrefixLen(in.ipPrefixLen()).gateway(in.gateway()).bridge(in.bridge())
|
||||
.portMapping(in.portMapping()).ports(in.ports()).sandboxId(in.sandboxId()).hairpinMode(in.hairpinMode()).linkLocalIPv6Address(in
|
||||
.linkLocalIPv6Address()).linkLocalIPv6PrefixLen(in.linkLocalIPv6PrefixLen()).sandboxKey(in.sandboxKey()).secondaryIPAddresses(in
|
||||
.secondaryIPAddresses()).secondaryIPv6Addresses(in.secondaryIPv6Addresses()).endpointId(in.endpointId()).globalIPv6Address(in
|
||||
.globalIPv6Address()).globalIPv6PrefixLen(in.globalIPv6PrefixLen()).ipv6Gateway(in.ipv6Gateway()).macAddress(in.macAddress())
|
||||
.networks(in.networks());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Node {
|
||||
|
||||
Node() {
|
||||
}
|
||||
|
||||
@SerializedNames({"IP"})
|
||||
public static Node create(String ip) {
|
||||
return new AutoValue_Node(ip);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract String ip();
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromNode(this);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private String ip;
|
||||
|
||||
public Builder ip(String ip) {
|
||||
this.ip = ip;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Node build() {
|
||||
return Node.create(this.ip);
|
||||
}
|
||||
|
||||
public Builder fromNode(Node in) {
|
||||
return this.ip(in.ip());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Port {
|
||||
@Nullable public abstract String ip();
|
||||
|
||||
public abstract int privatePort();
|
||||
|
||||
@Nullable public abstract Integer publicPort();
|
||||
|
||||
public abstract String type();
|
||||
|
||||
Port() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "IP", "PrivatePort", "PublicPort", "Type" })
|
||||
public static Port create(String ip, int privatePort, Integer publicPort, String type) {
|
||||
return new AutoValue_Port(ip, privatePort, publicPort, type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Resource {
|
||||
|
||||
public abstract String resource();
|
||||
|
||||
Resource() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "Resource" })
|
||||
public static Resource create(String resource) {
|
||||
return new AutoValue_Resource(resource);
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class State {
|
||||
|
||||
|
||||
public abstract int pid();
|
||||
|
||||
public abstract boolean running();
|
||||
|
||||
public abstract int exitCode();
|
||||
|
||||
public abstract String startedAt();
|
||||
|
||||
public abstract String finishedAt();
|
||||
|
||||
public abstract boolean paused();
|
||||
|
||||
public abstract boolean restarting();
|
||||
|
||||
@Nullable public abstract String status();
|
||||
|
||||
public abstract boolean oomKilled();
|
||||
|
||||
public abstract boolean dead();
|
||||
|
||||
@Nullable public abstract String error();
|
||||
|
||||
State() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "Pid", "Running", "ExitCode", "StartedAt", "FinishedAt", "Paused", "Restarting", "Status", "OOMKilled", "Dead", "Error" })
|
||||
public static State create(int pid, boolean running, int exitCode, String startedAt, String finishedAt,
|
||||
boolean paused, boolean restarting, String status, boolean oomKilled, boolean dead, String error) {
|
||||
return new AutoValue_State(pid, running, exitCode, startedAt, finishedAt, paused, restarting, status, oomKilled, dead, error);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class StatusCode {
|
||||
|
||||
public abstract int statusCode();
|
||||
|
||||
StatusCode() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "StatusCode" })
|
||||
public static StatusCode create(int statusCode) {
|
||||
return new AutoValue_StatusCode(statusCode);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Version {
|
||||
|
||||
public abstract String apiVersion();
|
||||
|
||||
public abstract String arch();
|
||||
|
||||
public abstract String gitCommit();
|
||||
|
||||
public abstract String goVersion();
|
||||
|
||||
public abstract String kernelVersion();
|
||||
|
||||
public abstract String os();
|
||||
|
||||
public abstract String version();
|
||||
|
||||
Version() {
|
||||
}
|
||||
|
||||
@SerializedNames({ "ApiVersion", "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
|
||||
public static Version create(String apiVersion, String arch, String gitCommit, String goVersion,
|
||||
String kernelVersion, String os, String version) {
|
||||
return new AutoValue_Version(apiVersion, arch, gitCommit, goVersion, kernelVersion, os, version);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
|
||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.Resource;
|
||||
import org.jclouds.docker.domain.StatusCode;
|
||||
import org.jclouds.docker.options.AttachOptions;
|
||||
import org.jclouds.docker.options.CommitOptions;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.docker.options.RemoveContainerOptions;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/v{jclouds.api-version}")
|
||||
public interface ContainerApi {
|
||||
|
||||
/**
|
||||
* @return a set of containers
|
||||
*/
|
||||
@Named("containers:list")
|
||||
@GET
|
||||
@Path("/containers/json")
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<ContainerSummary> listContainers();
|
||||
|
||||
/**
|
||||
* @param options the options to list the containers (@see ListContainerOptions)
|
||||
* @return a set of containers
|
||||
*/
|
||||
@Named("containers:list")
|
||||
@GET
|
||||
@Path("/containers/json")
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<ContainerSummary> listContainers(ListContainerOptions options);
|
||||
|
||||
/**
|
||||
* @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(NullOnNotFoundOr404.class)
|
||||
Container inspectContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be removed.
|
||||
*/
|
||||
@Named("container:delete")
|
||||
@DELETE
|
||||
@Path("/containers/{id}")
|
||||
void removeContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be started.
|
||||
*/
|
||||
@Named("container:start")
|
||||
@POST
|
||||
@Path("/containers/{id}/start")
|
||||
void startContainer(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be stopped.
|
||||
*/
|
||||
@Named("container:stop")
|
||||
@POST
|
||||
@Path("/containers/{id}/stop")
|
||||
void stopContainer(@PathParam("id") String containerId);
|
||||
|
||||
@Named("container:stop")
|
||||
@POST
|
||||
@Path("/containers/{id}/stop")
|
||||
void stopContainer(@PathParam("id") String containerId, @QueryParam("t") int secondsToWait);
|
||||
|
||||
/**
|
||||
* Create a new image from a container’s changes
|
||||
*
|
||||
* @return a new image created from the current container's status.
|
||||
*/
|
||||
@Named("container:commit")
|
||||
@POST
|
||||
@Path("/commit")
|
||||
Image commit();
|
||||
|
||||
/**
|
||||
* Create a new image from a container’s changes
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be paused.
|
||||
*/
|
||||
@Named("container:pause")
|
||||
@POST
|
||||
@Path("/containers/{id}/pause")
|
||||
void pause(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be unpaused.
|
||||
*/
|
||||
@Named("container:unpause")
|
||||
@POST
|
||||
@Path("/containers/{id}/unpause")
|
||||
void unpause(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be attached.
|
||||
*/
|
||||
@Named("container:attach")
|
||||
@POST
|
||||
@Path("/containers/{id}/attach")
|
||||
InputStream attach(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId The id of the container to be attached.
|
||||
* @param options the attach options @see org.jclouds.docker.options.AttachOptions
|
||||
*
|
||||
*/
|
||||
@Named("container:attach")
|
||||
@POST
|
||||
@Path("/containers/{id}/attach")
|
||||
InputStream attach(@PathParam("id") String containerId, AttachOptions options);
|
||||
|
||||
/**
|
||||
* Block until container @param containerId stops, then returns the exit code
|
||||
*/
|
||||
@Named("container:wait")
|
||||
@POST
|
||||
@Path("/containers/{id}/wait")
|
||||
StatusCode wait(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId restarts
|
||||
*/
|
||||
@Named("container:restart")
|
||||
@POST
|
||||
@Path("/containers/{id}/restart")
|
||||
void restart(@PathParam("id") String containerId);
|
||||
|
||||
@Named("container:restart")
|
||||
@POST
|
||||
@Path("/containers/{id}/restart")
|
||||
void restart(@PathParam("id") String containerId, @QueryParam("t") int secondsToWait);
|
||||
|
||||
|
||||
/**
|
||||
* @param containerId to be killed
|
||||
*/
|
||||
@Named("container:kill")
|
||||
@POST
|
||||
@Path("/containers/{id}/kill")
|
||||
void kill(@PathParam("id") String containerId);
|
||||
|
||||
/**
|
||||
* @param containerId to be killed
|
||||
* @param signal Signal to send to the container. When not set, SIGKILL is assumed and the call will waits for the
|
||||
* container to exit.
|
||||
*/
|
||||
@Named("container:kill")
|
||||
@POST
|
||||
@Path("/containers/{id}/kill")
|
||||
void kill(@PathParam("id") String containerId, @QueryParam("signal") int signal);
|
||||
|
||||
/**
|
||||
* @param containerId to be killed
|
||||
* @param signal Signal string like "SIGINT" to send to the container. When not set, SIGKILL is assumed and the call will waits for
|
||||
* the container to exit.
|
||||
*/
|
||||
@Named("container:kill")
|
||||
@POST
|
||||
@Path("/containers/{id}/kill")
|
||||
void kill(@PathParam("id") String containerId, @QueryParam("signal") String signal);
|
||||
|
||||
/**
|
||||
* @param containerId id of the container to copy files from
|
||||
*/
|
||||
@Named("container:copy")
|
||||
@POST
|
||||
@Path("/containers/{id}/copy")
|
||||
InputStream copy(@PathParam("id") String containerId, @BinderParam(BindToJsonPayload.class) Resource resource);
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
|
||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.ImageHistory;
|
||||
import org.jclouds.docker.domain.ImageSummary;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.docker.options.ListImageOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/v{jclouds.api-version}")
|
||||
public interface ImageApi {
|
||||
|
||||
/**
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<ImageSummary> listImages();
|
||||
|
||||
/**
|
||||
* @param options the configuration to list images (@see ListImageOptions)
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<ImageSummary> listImages(ListImageOptions options);
|
||||
|
||||
/**
|
||||
* Return low-level information on the image with given name. Not all fields from the returned {@link Image} instance
|
||||
* are populated by this method (e.g. {@link Image#repoTags()}).
|
||||
*
|
||||
* @param imageName The id of the image to inspect.
|
||||
* @return low-level information on the image name
|
||||
*/
|
||||
@Named("image:inspect")
|
||||
@GET
|
||||
@Path("/images/{name}/json")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
@Nullable
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Tag the image name into a repository.
|
||||
*
|
||||
* @param name
|
||||
* the name of the image to be tagged
|
||||
* @param repoName
|
||||
* the repository to tag in
|
||||
* @param tag
|
||||
* the new tag name
|
||||
* @param force
|
||||
* force create if tag already exists
|
||||
*/
|
||||
@Named("image:tag")
|
||||
@POST
|
||||
@Path("/images/{name}/tag")
|
||||
void tagImage(@PathParam("name") String name, @QueryParam("repo") String repoName,
|
||||
@QueryParam("tag") String tag, @QueryParam("force") boolean force);
|
||||
|
||||
/**
|
||||
* Return the history of the image with given {@code name}.
|
||||
*
|
||||
* @param name
|
||||
* the name of the image for which the history is retrieved
|
||||
*/
|
||||
@Named("image:history")
|
||||
@GET
|
||||
@Path("/images/{name}/history")
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<ImageHistory> getHistory(@PathParam("name") String name);
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Exec;
|
||||
import org.jclouds.docker.domain.ExecCreateParams;
|
||||
import org.jclouds.docker.domain.ExecInspect;
|
||||
import org.jclouds.docker.domain.ExecStartParams;
|
||||
import org.jclouds.docker.domain.Info;
|
||||
import org.jclouds.docker.domain.Version;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.docker.util.DockerInputStream;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/v{jclouds.api-version}")
|
||||
public interface MiscApi {
|
||||
|
||||
/**
|
||||
* Get the information of the current docker version.
|
||||
*
|
||||
* @return The information of the current docker version.
|
||||
*/
|
||||
@Named("version")
|
||||
@GET
|
||||
@Path("/version")
|
||||
Version getVersion();
|
||||
|
||||
/**
|
||||
* Get the information of the current docker version.
|
||||
*
|
||||
* @return The information of the current docker version.
|
||||
*/
|
||||
@Named("info")
|
||||
@GET
|
||||
@Path("/info")
|
||||
Info getInfo();
|
||||
|
||||
/**
|
||||
* Build an image from Dockerfile via stdin
|
||||
*
|
||||
* @param inputStream The stream must be a tar archive compressed with one of the following algorithms: identity
|
||||
* (no compression), gzip, bzip2, xz.
|
||||
* @return a stream of the build execution
|
||||
*/
|
||||
@Named("image:build")
|
||||
@POST
|
||||
@Path("/build")
|
||||
@Headers(keys = { "Content-Type", "Connection" }, values = { "application/tar", "close" })
|
||||
InputStream build(Payload inputStream);
|
||||
|
||||
/**
|
||||
* 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", "Connection" }, values = { "application/tar", "close" })
|
||||
InputStream build(Payload inputStream, BuildOptions options);
|
||||
|
||||
/**
|
||||
* Sets up an exec instance in a running container with given Id.
|
||||
*
|
||||
* @param containerId
|
||||
* container Id
|
||||
* @param execCreateParams
|
||||
* exec parameters
|
||||
* @return an instance which holds exec identifier
|
||||
*/
|
||||
@Named("container:exec")
|
||||
@POST
|
||||
@Path("/containers/{id}/exec")
|
||||
Exec execCreate(@PathParam("id") String containerId,
|
||||
@BinderParam(BindToJsonPayload.class) ExecCreateParams execCreateParams);
|
||||
|
||||
/**
|
||||
* Starts a previously set up exec instance id. If
|
||||
* {@link ExecStartParams#detach()} is true, this API returns after starting
|
||||
* the exec command. Otherwise, this API sets up an interactive session with
|
||||
* the exec command.
|
||||
*
|
||||
* @param execId
|
||||
* exec instance id
|
||||
* @param execStartParams
|
||||
* start parameters
|
||||
* @return raw docker stream which can be wrapped to
|
||||
* {@link DockerInputStream}
|
||||
* @see #execCreate(String, ExecCreateParams)
|
||||
* @see DockerInputStream
|
||||
*/
|
||||
@Named("exec:start")
|
||||
@POST
|
||||
@Path("/exec/{id}/start")
|
||||
InputStream execStart(@PathParam("id") String execId,
|
||||
@BinderParam(BindToJsonPayload.class) ExecStartParams execStartParams);
|
||||
|
||||
/**
|
||||
* Returns low-level information about the exec command id.
|
||||
*
|
||||
* @param execId
|
||||
* exec instance id
|
||||
* @return details about exec instance
|
||||
*/
|
||||
@Named("exec:inspect")
|
||||
@GET
|
||||
@Path("/exec/{id}/json")
|
||||
ExecInspect execInspect(@PathParam("id") String execId);
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
|
||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.annotations.Payload;
|
||||
import org.jclouds.rest.annotations.PayloadParam;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/v{jclouds.api-version}/networks")
|
||||
public interface NetworkApi {
|
||||
|
||||
/**
|
||||
* @return a set of networks
|
||||
*/
|
||||
@Named("networks:list")
|
||||
@GET
|
||||
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||
List<Network> listNetworks();
|
||||
|
||||
/**
|
||||
* @param network the network’s configuration (@see BindToJsonPayload)
|
||||
* @return a new network
|
||||
*/
|
||||
@Named("network:create")
|
||||
@POST
|
||||
@Path("/create")
|
||||
Network createNetwork(@BinderParam(BindToJsonPayload.class) Network network);
|
||||
|
||||
/**
|
||||
* Return low-level information on the network id
|
||||
* @param networkIdOrName The id or name of the network to get.
|
||||
* @return The details of the network or <code>null</code> if the network with the given id doesn't exist.
|
||||
*/
|
||||
@Named("network:inspect")
|
||||
@GET
|
||||
@Path("/{idOrName}")
|
||||
@Fallback(NullOnNotFoundOr404.class)
|
||||
Network inspectNetwork(@PathParam("idOrName") String networkIdOrName);
|
||||
|
||||
/**
|
||||
* @param networkIdOrName The id or name of the network to be removed.
|
||||
*/
|
||||
@Named("network:delete")
|
||||
@DELETE
|
||||
@Path("/{idOrName}")
|
||||
void removeNetwork(@PathParam("idOrName") String networkIdOrName);
|
||||
|
||||
/**
|
||||
* @param networkIdOrName The id or name of the network where the container will be attached.
|
||||
*/
|
||||
@Named("network:connectContainer")
|
||||
@POST
|
||||
@Path("/{idOrName}/connect")
|
||||
@Payload("%7B\"Container\":\"{containerIdOrName}\"%7D")
|
||||
@Headers(keys = "Content-Type", values = "application/json")
|
||||
void connectContainerToNetwork(@PathParam("idOrName") String networkIdOrName, @PayloadParam("containerIdOrName") String containerIdOrName);
|
||||
|
||||
/**
|
||||
* @param networkIdOrName The id or name of the network where the container was attached.
|
||||
*/
|
||||
@Named("network:disconnectContainer")
|
||||
@POST
|
||||
@Path("/{idOrName}/disconnect")
|
||||
@Payload("%7B\"Container\":\"{containerIdOrName}\"%7D")
|
||||
@Headers(keys = "Content-Type", values = "application/json")
|
||||
void disconnectContainerFromNetwork(@PathParam("idOrName") String networkIdOrName, @PayloadParam("containerIdOrName") String containerIdOrName);
|
||||
|
||||
}
|
|
@ -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.handlers;
|
||||
|
||||
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
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 com.google.common.base.Throwables;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
closeQuietly(response.getPayload());
|
||||
command.setException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public String parseMessage(HttpResponse response) {
|
||||
if (response.getPayload() == null)
|
||||
return null;
|
||||
try {
|
||||
return Strings2.toStringAndClose(response.getPayload().openStream());
|
||||
} catch (IOException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public class NullSafeCopies {
|
||||
|
||||
public static <K, V> Map<K, V> copyOf(@Nullable Map<K, V> map) {
|
||||
return map != null ? ImmutableMap.copyOf(map) : ImmutableMap.<K, V> of();
|
||||
}
|
||||
|
||||
public static <E> List<E> copyOf(@Nullable List<E> list) {
|
||||
return list != null ? ImmutableList.copyOf(list) : ImmutableList.<E> of();
|
||||
}
|
||||
|
||||
public static <E> List<E> copyOf(@Nullable Iterable<E> list) {
|
||||
return list != null ? ImmutableList.copyOf(list) : ImmutableList.<E> of();
|
||||
}
|
||||
|
||||
public static <E> List<E> copyOf(@Nullable E[] array) {
|
||||
return array != null ? ImmutableList.copyOf(array) : ImmutableList.<E> of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies given List with keeping null value if provided.
|
||||
*
|
||||
* @param list
|
||||
* instance to copy (maybe <code>null</code>)
|
||||
* @return if the parameter is not-<code>null</code> then immutable copy;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
public static <E> List<E> copyWithNullOf(@Nullable List<E> list) {
|
||||
return list != null ? ImmutableList.copyOf(list) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies given Map with keeping null value if provided.
|
||||
*
|
||||
* @param map
|
||||
* instance to copy (maybe <code>null</code>)
|
||||
* @return if the parameter is not-<code>null</code> then immutable copy;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
public static <K, V> Map<K, V> copyWithNullOf(@Nullable Map<K, V> map) {
|
||||
return map != null ? ImmutableMap.copyOf(map) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies given {@link Iterable} into immutable {@link List} with keeping null value if provided.
|
||||
*
|
||||
* @param iterable
|
||||
* instance to copy (maybe <code>null</code>)
|
||||
* @return if the parameter is not-<code>null</code> then immutable copy;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
public static <E> List<E> copyWithNullOf(@Nullable Iterable<E> iterable) {
|
||||
return iterable != null ? ImmutableList.copyOf(iterable) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies given array into immutable {@link List} with keeping null value if provided.
|
||||
*
|
||||
* @param array
|
||||
* instance to copy (maybe <code>null</code>)
|
||||
* @return if the parameter is not-<code>null</code> then immutable copy;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
public static <E> List<E> copyWithNullOf(@Nullable E[] array) {
|
||||
return array != null ? ImmutableList.copyOf(array) : null;
|
||||
}
|
||||
|
||||
private NullSafeCopies() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class AttachOptions extends BaseHttpRequestOptions {
|
||||
|
||||
/**
|
||||
* @param stream When TTY is enabled, the stream is the raw data from the process PTY and client's stdin.
|
||||
* When TTY is disabled, the stream is multiplexed to separate stdout and stderr.
|
||||
* @return AttachOptions
|
||||
*/
|
||||
public AttachOptions stream(boolean stream) {
|
||||
this.queryParameters.put("stream", String.valueOf(stream));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param logs require logs to be attached. Default false.
|
||||
* @return AttachOptions
|
||||
*/
|
||||
public AttachOptions logs(boolean logs) {
|
||||
this.queryParameters.put("logs", String.valueOf(logs));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdin if stream=true, attach to stdin. Default false
|
||||
* @return AttachOptions
|
||||
*/
|
||||
public AttachOptions stdin(boolean stdin) {
|
||||
this.queryParameters.put("stdin", String.valueOf(stdin));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stdout if logs=true, return stdout log, if stream=true, attach to stdout. Default false
|
||||
* @return
|
||||
*/
|
||||
public AttachOptions stdout(boolean stdout) {
|
||||
this.queryParameters.put("stdout", String.valueOf(stdout));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param stderr if logs=true, return stderr log, if stream=true, attach to stderr. Default false
|
||||
* @return
|
||||
*/
|
||||
public AttachOptions stderr(boolean stderr) {
|
||||
this.queryParameters.put("stderr", String.valueOf(stderr));
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see org.jclouds.docker.options.AttachOptions#stream
|
||||
*/
|
||||
public static AttachOptions stream(boolean stream) {
|
||||
AttachOptions options = new AttachOptions();
|
||||
return options.stream(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.docker.options.AttachOptions#logs(Boolean)
|
||||
*/
|
||||
public static AttachOptions logs(boolean logs) {
|
||||
AttachOptions options = new AttachOptions();
|
||||
return options.logs(logs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.docker.options.AttachOptions#stdin(Boolean)
|
||||
*/
|
||||
public static AttachOptions stdin(boolean stdin) {
|
||||
AttachOptions options = new AttachOptions();
|
||||
return options.stdin(stdin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.docker.options.AttachOptions#stdout(Boolean)
|
||||
*/
|
||||
public static AttachOptions stdout(boolean stdout) {
|
||||
AttachOptions options = new AttachOptions();
|
||||
return options.stdout(stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.docker.options.AttachOptions#stderr(Boolean)
|
||||
*/
|
||||
public static AttachOptions stderr(boolean stderr) {
|
||||
AttachOptions options = new AttachOptions();
|
||||
return options.stderr(stderr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class BuildOptions extends BaseHttpRequestOptions {
|
||||
|
||||
public BuildOptions tag(String tag) {
|
||||
this.queryParameters.put("t", tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuildOptions verbose(boolean verbose) {
|
||||
this.queryParameters.put("verbose", String.valueOf(verbose));
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuildOptions nocache(boolean nocache) {
|
||||
this.queryParameters.put("nocache", String.valueOf(nocache));
|
||||
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,104 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class CommitOptions extends BaseHttpRequestOptions {
|
||||
|
||||
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,90 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class CreateImageOptions extends BaseHttpRequestOptions {
|
||||
|
||||
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,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.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class DeleteImageOptions extends BaseHttpRequestOptions {
|
||||
|
||||
public DeleteImageOptions force(boolean force) {
|
||||
this.queryParameters.put("force", String.valueOf(force));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteImageOptions noPrune(boolean noPrune) {
|
||||
this.queryParameters.put("noPrune", String.valueOf(noPrune));
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see DeleteImageOptions#force
|
||||
*/
|
||||
public static DeleteImageOptions force(boolean force) {
|
||||
DeleteImageOptions options = new DeleteImageOptions();
|
||||
return options.force(force);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DeleteImageOptions#noPrune
|
||||
*/
|
||||
public static DeleteImageOptions noPrune(boolean noPrune) {
|
||||
DeleteImageOptions options = new DeleteImageOptions();
|
||||
return options.noPrune(noPrune);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class ListContainerOptions extends BaseHttpRequestOptions {
|
||||
|
||||
public ListContainerOptions all(boolean all) {
|
||||
this.queryParameters.put("all", String.valueOf(all));
|
||||
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,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.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class ListImageOptions extends BaseHttpRequestOptions {
|
||||
|
||||
public ListImageOptions all(boolean all) {
|
||||
this.queryParameters.put("all", String.valueOf(all));
|
||||
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,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.options;
|
||||
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
public class RemoveContainerOptions extends BaseHttpRequestOptions {
|
||||
|
||||
public RemoveContainerOptions verbose(boolean verbose) {
|
||||
this.queryParameters.put("verbose", String.valueOf(verbose));
|
||||
return this;
|
||||
}
|
||||
|
||||
public RemoveContainerOptions force(boolean force) {
|
||||
this.queryParameters.put("force", String.valueOf(force));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the volumes associated to the container
|
||||
*
|
||||
* @param volume If set to true the volume associated to the container will be removed.
|
||||
* Otherwise it will not be removed.
|
||||
*/
|
||||
public RemoveContainerOptions volume(boolean volume) {
|
||||
this.queryParameters.put("v", String.valueOf(volume));
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RemoveContainerOptions#volume
|
||||
*/
|
||||
public static RemoveContainerOptions volume(boolean volume) {
|
||||
RemoveContainerOptions options = new RemoveContainerOptions();
|
||||
return options.volume(volume);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
import org.jclouds.docker.DockerApiMetadata;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.location.Provider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static org.jclouds.docker.suppliers.SSLContextBuilder.isClientKeyAndCertificateData;
|
||||
|
||||
@Singleton
|
||||
public class DockerSSLContextSupplier implements Supplier<SSLContext> {
|
||||
private final Supplier<Credentials> creds;
|
||||
private final String caCertPath;
|
||||
private final String caCertData;
|
||||
|
||||
@Inject
|
||||
DockerSSLContextSupplier(@Provider Supplier<Credentials> creds, @Named(DockerApiMetadata.DOCKER_CA_CERT_PATH) String caCertPath, @Named(DockerApiMetadata.DOCKER_CA_CERT_DATA) String caCertData) {
|
||||
this.creds = creds;
|
||||
this.caCertPath = caCertPath;
|
||||
this.caCertData = caCertData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext get() {
|
||||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
try {
|
||||
SSLContextBuilder builder = new SSLContextBuilder();
|
||||
if (isClientKeyAndCertificateData(currentCreds.credential, currentCreds.identity)) {
|
||||
builder.clientKeyAndCertificateData(currentCreds.credential, currentCreds.identity);
|
||||
} else {
|
||||
builder.clientKeyAndCertificatePaths(currentCreds.credential, currentCreds.identity);
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(caCertPath)) {
|
||||
builder.caCertificatePath(caCertPath);
|
||||
} else if (!Strings.isNullOrEmpty(caCertData)) {
|
||||
builder.caCertificateData(caCertData);
|
||||
}
|
||||
return builder.build();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw propagate(e);
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.config.SSLModule;
|
||||
import org.jclouds.location.Provider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static org.jclouds.docker.suppliers.SSLContextBuilder.isClientKeyAndCertificateData;
|
||||
|
||||
@Singleton
|
||||
public class DockerUntrustedSSLContextSupplier implements Supplier<SSLContext> {
|
||||
private final Supplier<Credentials> creds;
|
||||
private final SSLModule.TrustAllCerts insecureTrustManager;
|
||||
|
||||
@Inject
|
||||
DockerUntrustedSSLContextSupplier(@Provider Supplier<Credentials> creds,
|
||||
SSLModule.TrustAllCerts insecureTrustManager) {
|
||||
this.creds = creds;
|
||||
this.insecureTrustManager = insecureTrustManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext get() {
|
||||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
try {
|
||||
SSLContextBuilder builder = new SSLContextBuilder();
|
||||
if (isClientKeyAndCertificateData(currentCreds.credential, currentCreds.identity)) {
|
||||
builder.clientKeyAndCertificateData(currentCreds.credential, currentCreds.identity);
|
||||
} else if (new File(currentCreds.identity).isFile() && new File(currentCreds.credential).isFile()) {
|
||||
builder.clientKeyAndCertificatePaths(currentCreds.credential, currentCreds.identity);
|
||||
}
|
||||
builder.trustManager(insecureTrustManager);
|
||||
return builder.build();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw propagate(e);
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.util.Closeables2;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.Socket;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
|
||||
public class SSLContextBuilder {
|
||||
|
||||
private KeyManager[] keyManagers;
|
||||
private TrustManager[] trustManagers;
|
||||
|
||||
public static final boolean isClientKeyAndCertificateData(String key, String cert) {
|
||||
return (key.startsWith(Pems.PRIVATE_PKCS1_MARKER) || key.startsWith(Pems.PRIVATE_PKCS8_MARKER)) &&
|
||||
cert.startsWith(Pems.CERTIFICATE_X509_MARKER);
|
||||
}
|
||||
|
||||
public SSLContextBuilder() { }
|
||||
|
||||
public SSLContextBuilder clientKeyAndCertificatePaths(String keyPath, String certPath) throws IOException, CertificateException {
|
||||
X509Certificate certificate = getCertificate(loadFile(certPath));
|
||||
PrivateKey privateKey = getKey(loadFile(keyPath));
|
||||
keyManager(new InMemoryKeyManager(certificate, privateKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder clientKeyAndCertificateData(String keyData, String certData) throws CertificateException {
|
||||
X509Certificate certificate = getCertificate(certData);
|
||||
PrivateKey privateKey = getKey(keyData);
|
||||
keyManager(new InMemoryKeyManager(certificate, privateKey));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder caCertificatePath(String caCertPath) {
|
||||
try {
|
||||
trustManagers = getTrustManagerWithCaCert(loadFile(caCertPath));
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder caCertificateData(String caCertPath) {
|
||||
trustManagers = getTrustManagerWithCaCert(caCertPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder keyManager(KeyManager keyManager) {
|
||||
keyManagers = new KeyManager[] { keyManager };
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContextBuilder trustManager(TrustManager trustManager) {
|
||||
trustManagers = new TrustManager[] { trustManager };
|
||||
return this;
|
||||
}
|
||||
|
||||
public SSLContext build() throws NoSuchAlgorithmException, KeyManagementException {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(keyManagers, trustManagers, new SecureRandom());
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
private TrustManager[] getTrustManagerWithCaCert(String caCertData) {
|
||||
try {
|
||||
X509Certificate caCert = getCertificate(caCertData);
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
trustStore.setCertificateEntry("ca", caCert);
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(trustStore);
|
||||
return tmf.getTrustManagers();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw propagate(e);
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static X509Certificate getCertificate(String certificate) {
|
||||
try {
|
||||
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(
|
||||
new ByteArrayInputStream(certificate.getBytes(Charsets.UTF_8)));
|
||||
} catch (CertificateException ex) {
|
||||
throw new RuntimeException("Invalid certificate", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static PrivateKey getKey(String privateKey) {
|
||||
PEMParser pemParser = new PEMParser(new StringReader(privateKey));
|
||||
try {
|
||||
Object object = pemParser.readObject();
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
|
||||
KeyPair keyPair = converter.getKeyPair((PEMKeyPair) object);
|
||||
return keyPair.getPrivate();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Invalid private key", ex);
|
||||
} finally {
|
||||
Closeables2.closeQuietly(pemParser);
|
||||
}
|
||||
}
|
||||
|
||||
private static String loadFile(final String filePath) throws IOException {
|
||||
return Files.toString(new File(filePath), Charsets.UTF_8);
|
||||
}
|
||||
|
||||
private static class InMemoryKeyManager extends X509ExtendedKeyManager {
|
||||
private static final String DEFAULT_ALIAS = "docker";
|
||||
|
||||
private final X509Certificate certificate;
|
||||
|
||||
private final PrivateKey privateKey;
|
||||
|
||||
public InMemoryKeyManager(final X509Certificate certificate, final PrivateKey privateKey) throws CertificateException {
|
||||
this.certificate = certificate;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseClientAlias(final String[] keyType, final Principal[] issuers, final Socket socket) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String chooseServerAlias(final String keyType, final Principal[] issuers, final Socket socket) {
|
||||
return DEFAULT_ALIAS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain(final String alias) {
|
||||
return new X509Certificate[] { certificate };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getClientAliases(final String keyType, final Principal[] issuers) {
|
||||
return new String[] { DEFAULT_ALIAS };
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrivateKey getPrivateKey(final String alias) {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getServerAliases(final String keyType, final Principal[] issuers) {
|
||||
return new String[] { DEFAULT_ALIAS };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Extension to {@link DataInputStream} which adds method
|
||||
* {@link #readStdStreamData()} to allow read multiplexed standard streams.
|
||||
*/
|
||||
public final class DockerInputStream extends DataInputStream {
|
||||
|
||||
/**
|
||||
* Ctor from superclass.
|
||||
*
|
||||
* @param in
|
||||
* @see DataInputStream#DataInputStream(InputStream)
|
||||
*/
|
||||
public DockerInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link StdStreamData} instance read from the input stream or
|
||||
* <code>null</code> if we reached end of the stream.
|
||||
* @throws IOException
|
||||
*/
|
||||
public StdStreamData readStdStreamData() throws IOException {
|
||||
byte[] header = new byte[8];
|
||||
// try to read first byte from the message header - just to check if we
|
||||
// are at the end
|
||||
// of stream
|
||||
if (-1 == read(header, 0, 1)) {
|
||||
return null;
|
||||
}
|
||||
// read the rest of the header
|
||||
readFully(header, 1, 7);
|
||||
// decode size as an unsigned int
|
||||
long size = (long) (header[4] & 0xFF) << 24 | (header[5] & 0xFF) << 16 | (header[6] & 0xFF) << 8
|
||||
| (header[7] & 0xFF);
|
||||
|
||||
byte[] payload;
|
||||
// The size from the header is an unsigned int so it can happen the byte
|
||||
// array has not a sufficient size and we'll have to truncate the frame
|
||||
payload = new byte[(int) Math.min(Integer.MAX_VALUE, size)];
|
||||
readFully(payload);
|
||||
boolean truncated = false;
|
||||
if (size > Integer.MAX_VALUE) {
|
||||
truncated = true;
|
||||
// skip the rest
|
||||
readFully(new byte[(int) (size - Integer.MAX_VALUE)]);
|
||||
}
|
||||
return new StdStreamData(header[0], payload, truncated);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Representation of single message from docker-raw-stream. It holds stream
|
||||
* type, data (payload) and flag which says if the payload was truncated. The
|
||||
* truncation can occur when the frame size is greater than
|
||||
* {@link Integer#MAX_VALUE}.
|
||||
*/
|
||||
public final class StdStreamData {
|
||||
|
||||
private final StdStreamType type;
|
||||
private final byte[] payload;
|
||||
private final boolean truncated;
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
*
|
||||
* @param streamTypeId
|
||||
* standard stream type (0=stdIn, 1=stdOut, 2=stdErr)
|
||||
* @param payload
|
||||
* message data - must not be <code>null</code>
|
||||
* @param truncated
|
||||
* @throws ArrayIndexOutOfBoundsException
|
||||
* if streamTypeId is not an index in {@link StdStreamType} enum.
|
||||
* @throws NullPointerException
|
||||
* if provided payload is <code>null</code>
|
||||
*/
|
||||
StdStreamData(byte streamTypeId, byte[] payload, boolean truncated)
|
||||
throws ArrayIndexOutOfBoundsException, NullPointerException {
|
||||
this.type = StdStreamType.values()[streamTypeId];
|
||||
this.payload = Arrays.copyOf(payload, payload.length);
|
||||
this.truncated = truncated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of stream.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public StdStreamType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data from this message.
|
||||
*
|
||||
* @return payload.
|
||||
*/
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag which says if the payload was truncated (because of size).
|
||||
*
|
||||
* @return true if truncated
|
||||
*/
|
||||
public boolean isTruncated() {
|
||||
return truncated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard streams enum. The order of entries is important!
|
||||
*/
|
||||
public static enum StdStreamType {
|
||||
IN, OUT, ERR;
|
||||
}
|
||||
}
|
|
@ -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,101 @@
|
|||
/*
|
||||
* 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 com.google.common.base.Charsets.UTF_8;
|
||||
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.shrinkwrap.api.GenericArchive;
|
||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||
import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
|
||||
import org.jboss.shrinkwrap.api.exporter.TarExporter;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.apis.BaseApiLiveTest;
|
||||
import org.jclouds.compute.config.ComputeServiceProperties;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.internal.DockerTestUtils;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.inject.Module;
|
||||
|
||||
@Test(groups = "live")
|
||||
public class BaseDockerApiLiveTest extends BaseApiLiveTest<DockerApi> {
|
||||
|
||||
protected static final String DEFAULT_IMAGE = "alpine";
|
||||
protected static final String DEFAULT_TAG = "3.3";
|
||||
protected static final String ALPINE_IMAGE_TAG = String.format("%s:%s", DEFAULT_IMAGE, DEFAULT_TAG);
|
||||
|
||||
|
||||
public BaseDockerApiLiveTest() {
|
||||
provider = "docker";
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes Docker image if it's present on the Docker host.
|
||||
*
|
||||
* @param imageName
|
||||
* image to be deleted (must be not-<code>null</code>)
|
||||
* @see DockerTestUtils#removeImageIfExists(DockerApi, String)
|
||||
*/
|
||||
protected void removeImageIfExists(String imageName) {
|
||||
DockerTestUtils.removeImageIfExists(api, imageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Module> setupModules() {
|
||||
return ImmutableSet.<Module>of(getLoggingModule(), new SshjSshClientModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties overrides = super.setupProperties();
|
||||
overrides.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
|
||||
setIfTestSystemPropertyPresent(overrides, provider + ".cacert.path");
|
||||
setIfTestSystemPropertyPresent(overrides, Constants.PROPERTY_TRUST_ALL_CERTS);
|
||||
return overrides;
|
||||
}
|
||||
|
||||
protected String consumeStream(InputStream stream) {
|
||||
try {
|
||||
return CharStreams.toString(new InputStreamReader(stream, UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
} finally {
|
||||
closeQuietly(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static Payload tarredDockerfile() throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
ShrinkWrap.create(GenericArchive.class, "archive.tar")
|
||||
.add(new ClassLoaderAsset("Dockerfile"), "Dockerfile")
|
||||
.as(TarExporter.class).exportTo(bytes);
|
||||
|
||||
return Payloads.newByteArrayPayload(bytes.toByteArray());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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.assertTrue;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.compute.options.DockerTemplateOptions;
|
||||
import org.jclouds.docker.compute.strategy.DockerComputeServiceAdapter;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.docker.features.NetworkApi;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
|
||||
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceAdapterLiveTest")
|
||||
public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String SSHABLE_IMAGE = "kwart/alpine-ext";
|
||||
private static final String SSHABLE_IMAGE_TAG = "3.3-ssh";
|
||||
private Image defaultImage;
|
||||
private Network network1;
|
||||
private Network network2;
|
||||
|
||||
private DockerComputeServiceAdapter adapter;
|
||||
private TemplateBuilder templateBuilder;
|
||||
private NodeAndInitialCredentials<Container> guest;
|
||||
private static final String CHUANWEN_COWSAY = "chuanwen/cowsay";
|
||||
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
super.initialize();
|
||||
String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
|
||||
defaultImage = adapter.getImage(imageName);
|
||||
network1 = createAndInspectNetwork("network1");
|
||||
network2 = createAndInspectNetwork("network2");
|
||||
assertNotNull(defaultImage);
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
protected void tearDown() {
|
||||
if (guest != null) {
|
||||
adapter.destroyNode(guest.getNode().id() + "");
|
||||
}
|
||||
if (api.getImageApi().inspectImage(CHUANWEN_COWSAY) != null) {
|
||||
api.getImageApi().deleteImage(CHUANWEN_COWSAY);
|
||||
}
|
||||
if (api.getNetworkApi().inspectNetwork("network1") != null) {
|
||||
api.getNetworkApi().removeNetwork("network1");
|
||||
}
|
||||
if (api.getNetworkApi().inspectNetwork("network2") != null) {
|
||||
api.getNetworkApi().removeNetwork("network2");
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@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 name = "container" + new Random().nextInt();
|
||||
Template template = templateBuilder.imageId(defaultImage.id()).build();
|
||||
DockerTemplateOptions options = template.getOptions().as(DockerTemplateOptions.class);
|
||||
options.env(ImmutableList.of("ROOT_PASSWORD=password"));
|
||||
guest = adapter.createNodeWithGroupEncodedIntoName("test", name, template);
|
||||
assertEquals(guest.getNodeId(), guest.getNode().id());
|
||||
}
|
||||
|
||||
public void testListHardwareProfiles() {
|
||||
Iterable<Hardware> profiles = adapter.listHardwareProfiles();
|
||||
assertFalse(Iterables.isEmpty(profiles));
|
||||
|
||||
for (Hardware profile : profiles) {
|
||||
assertNotNull(profile);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetImageNotHiddenByCache() {
|
||||
// Ensure image to be tested is unknown to jclouds and docker and that
|
||||
// cache is warm
|
||||
assertNull(findImageFromListImages(CHUANWEN_COWSAY));
|
||||
assertNull(api.getImageApi().inspectImage(CHUANWEN_COWSAY));
|
||||
|
||||
// Get new image
|
||||
adapter.getImage(CHUANWEN_COWSAY);
|
||||
|
||||
assertNotNull(findImageFromListImages(CHUANWEN_COWSAY),
|
||||
"New image is not available from listImages presumably due to caching");
|
||||
}
|
||||
|
||||
public void testCreateNodeWithMultipleNetworks() {
|
||||
String name = "container" + new Random().nextInt();
|
||||
Template template = templateBuilder.imageId(defaultImage.id()).build();
|
||||
DockerTemplateOptions options = template.getOptions().as(DockerTemplateOptions.class);
|
||||
options.env(ImmutableList.of("ROOT_PASSWORD=password"));
|
||||
options.networkMode("bridge");
|
||||
options.networks(network1.name(), network2.name());
|
||||
guest = adapter.createNodeWithGroupEncodedIntoName("test", name, template);
|
||||
|
||||
assertTrue(guest.getNode().networkSettings().networks().containsKey("network1"));
|
||||
assertTrue(guest.getNode().networkSettings().networks().containsKey("network2"));
|
||||
assertEquals(guest.getNode().networkSettings().networks().size(), 3);
|
||||
}
|
||||
|
||||
private Image findImageFromListImages(final String image) {
|
||||
return Iterables.find(adapter.listImages(), new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image input) {
|
||||
for (String tag : input.repoTags()) {
|
||||
if (tag.equals(CHUANWEN_COWSAY + DockerComputeServiceAdapter.SUFFIX_LATEST_VERSION)
|
||||
|| tag.equals(DockerComputeServiceAdapter.PREFIX_DOCKER_HUB_HOST + CHUANWEN_COWSAY
|
||||
+ DockerComputeServiceAdapter.SUFFIX_LATEST_VERSION)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Module> setupModules() {
|
||||
return ImmutableSet.<Module> of(getLoggingModule(), new SshjSshClientModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates network (driver="bridge") with given name and then inspects it to
|
||||
* fully populate the returned {@link Network} object.
|
||||
*
|
||||
* @param networkName
|
||||
*/
|
||||
private Network createAndInspectNetwork(final String networkName) {
|
||||
final NetworkApi networkApi = api.getNetworkApi();
|
||||
Network network = networkApi.createNetwork(Network.builder().name(networkName).driver("bridge").build());
|
||||
return networkApi.inspectNetwork(network.id());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* 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 com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static java.util.logging.Logger.getAnonymousLogger;
|
||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.runAsRoot;
|
||||
import static org.jclouds.util.Predicates2.retry;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.JettyStatements;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.compute.util.OpenSocketFinder;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.compute.options.DockerTemplateOptions;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.features.ImageApi;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.predicates.SocketOpen;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Live tests for the {@link org.jclouds.compute.ComputeService} integration.
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceLiveTest")
|
||||
public class DockerComputeServiceLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
|
||||
private static final String SSHABLE_IMAGE = "tutum/ubuntu";
|
||||
private static final String SSHABLE_IMAGE_TAG = "trusty";
|
||||
private Image defaultImage;
|
||||
protected Template template;
|
||||
protected Predicate<HostAndPort> socketTester;
|
||||
protected OpenSocketFinder openSocketFinder;
|
||||
|
||||
protected ComputeService client;
|
||||
|
||||
public DockerComputeServiceLiveTest() {
|
||||
provider = "docker";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module getSshModule() {
|
||||
return new SshjSshClientModule();
|
||||
}
|
||||
|
||||
@BeforeGroups(groups = { "integration", "live" })
|
||||
@Override
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
buildSocketTester();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeContext() {
|
||||
super.initializeContext();
|
||||
client = view.getComputeService();
|
||||
|
||||
String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
|
||||
defaultImage = client.getImage(imageName);
|
||||
assertNotNull(defaultImage);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@Override
|
||||
protected void tearDownContext() {
|
||||
super.tearDownContext();
|
||||
if (defaultImage != null) {
|
||||
imageApi().deleteImage(SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG, DeleteImageOptions.Builder.force(true));
|
||||
}
|
||||
}
|
||||
|
||||
private ImageApi imageApi() {
|
||||
return client.getContext().unwrapApi(DockerApi.class).getImageApi();
|
||||
}
|
||||
|
||||
protected Template buildTemplate(TemplateBuilder templateBuilder) {
|
||||
|
||||
String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
|
||||
org.jclouds.docker.domain.Image image = imageApi().inspectImage(imageName);
|
||||
if (image == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
|
||||
imageApi().createImage(options);
|
||||
}
|
||||
image = imageApi().inspectImage(imageName);
|
||||
defaultImage = client.getImage(image.id());
|
||||
|
||||
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
options.env(ImmutableList.of("ROOT_PASS=password"));
|
||||
options.overrideLoginCredentials(LoginCredentials.builder().identity("root").credential("password").build());
|
||||
template = templateBuilder.imageId(defaultImage.getId()).options(options).build();
|
||||
return template;
|
||||
}
|
||||
|
||||
protected void createAndRunAServiceInGroup(String group) throws RunNodesException {
|
||||
// note that some cloud providers do not support mixed case tag names
|
||||
ImmutableMap<String, String> userMetadata = ImmutableMap.of("test", group);
|
||||
ImmutableSet<String> tags = ImmutableSet.of(group);
|
||||
Stopwatch watch = Stopwatch.createStarted();
|
||||
template = buildTemplate(client.templateBuilder());
|
||||
template.getOptions().inboundPorts(22, 8080).blockOnPort(22, 300).userMetadata(userMetadata).tags(tags);
|
||||
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template));
|
||||
long createSeconds = watch.elapsed(TimeUnit.SECONDS);
|
||||
final String nodeId = node.getId();
|
||||
//checkUserMetadataContains(node, userMetadata);
|
||||
//checkTagsInNodeEquals(node, tags);
|
||||
getAnonymousLogger().info(
|
||||
format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
|
||||
watch.reset().start();
|
||||
client.runScriptOnNode(nodeId, JettyStatements.install(), nameTask("configure-jetty"));
|
||||
long configureSeconds = watch.elapsed(TimeUnit.SECONDS);
|
||||
getAnonymousLogger().info(
|
||||
format(
|
||||
"<< configured node(%s) with %s and jetty %s in %ss",
|
||||
nodeId,
|
||||
exec(nodeId, "java -fullversion"),
|
||||
exec(nodeId, JettyStatements.version()), configureSeconds));
|
||||
trackProcessOnNode(JettyStatements.start(), "start jetty", node);
|
||||
client.runScriptOnNode(nodeId, JettyStatements.stop(), runAsRoot(false).wrapInInitScript(false));
|
||||
trackProcessOnNode(JettyStatements.start(), "start jetty", node);
|
||||
}
|
||||
|
||||
protected void trackProcessOnNode(Statement process, String processName, NodeMetadata node) {
|
||||
ServiceStats stats = new ServiceStats();
|
||||
Stopwatch watch = Stopwatch.createStarted();
|
||||
ExecResponse exec = client.runScriptOnNode(node.getId(), process, runAsRoot(false).wrapInInitScript(false));
|
||||
stats.backgroundProcessMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
|
||||
|
||||
Container container = client.getContext().unwrapApi(DockerApi.class).getContainerApi().inspectContainer(node.getId());
|
||||
Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
|
||||
int port = Integer.parseInt(getOnlyElement(ports.get("8080/tcp")).get("HostPort"));
|
||||
|
||||
watch.reset().start();
|
||||
HostAndPort socket;
|
||||
try {
|
||||
socket = openSocketFinder.findOpenSocketOnNode(node, port, 600, TimeUnit.SECONDS);
|
||||
} catch (NoSuchElementException e) {
|
||||
throw new NoSuchElementException(format("%s%n%s%s", e.getMessage(), exec.getOutput(), exec.getError()));
|
||||
}
|
||||
stats.socketOpenMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
|
||||
getAnonymousLogger().info(format("<< %s on node(%s)[%s] %s", processName, node.getId(), socket, stats));
|
||||
}
|
||||
|
||||
static class ServiceStats {
|
||||
long backgroundProcessMilliseconds;
|
||||
long socketOpenMilliseconds;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return format("[backgroundProcessMilliseconds=%s, socketOpenMilliseconds=%s]",
|
||||
backgroundProcessMilliseconds, socketOpenMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
protected String exec(final String nodeId, String command) {
|
||||
return exec(nodeId, Statements.exec(command));
|
||||
}
|
||||
|
||||
protected String exec(final String nodeId, Statement command) {
|
||||
return client.runScriptOnNode(nodeId, command, runAsRoot(false).wrapInInitScript(false)).getOutput().trim();
|
||||
}
|
||||
|
||||
protected void buildSocketTester() {
|
||||
SocketOpen socketOpen = view.utils().injector().getInstance(SocketOpen.class);
|
||||
socketTester = retry(socketOpen, 60, 1, SECONDS);
|
||||
// wait a maximum of 60 seconds for port 8080 to open.
|
||||
openSocketFinder = context.utils().injector().getInstance(OpenSocketFinder.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* 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.assertj.core.api.Assertions.assertThat;
|
||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
|
||||
import static org.jclouds.docker.internal.DockerTestUtils.consumeStreamSilently;
|
||||
import static org.jclouds.docker.internal.DockerTestUtils.removeImageIfExists;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.compute.functions.LoginPortForContainer;
|
||||
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.domain.ImageSummary;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* This class tests configuring custom SSH port for Docker images.
|
||||
*/
|
||||
@Test(groups = "live", testName = "SshToCustomPortLiveTest", singleThreaded = true)
|
||||
public class SshToCustomPortLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
|
||||
private static final int SSH_PORT = 8822;
|
||||
private static final int SSH_PORT_BRIDGE = 18822;
|
||||
private static final String IMAGE_REPOSITORY = "jclouds/testrepo";
|
||||
private static final String IMAGE_TAG_1 = "testtag";
|
||||
private static final String IMAGE_TAG_2 = "second";
|
||||
|
||||
private Image image;
|
||||
|
||||
public SshToCustomPortLiveTest() {
|
||||
provider = "docker";
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the new image exists and tags were created successfully in
|
||||
* the test preparation phase ({@link #setupContext()} method).
|
||||
*/
|
||||
@Test
|
||||
public void testImageCreated() {
|
||||
assertNotNull(image);
|
||||
|
||||
final String imageId = image.id();
|
||||
assertNotNull(imageId);
|
||||
|
||||
List<ImageSummary> listImages = api().getImageApi().listImages();
|
||||
assertNotNull(listImages);
|
||||
ImageSummary testImage = Iterables.find(listImages, new Predicate<ImageSummary>() {
|
||||
@Override
|
||||
public boolean apply(ImageSummary input) {
|
||||
return imageId.equals(input.id());
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(testImage.repoTags().size(), 2, "Unexpected number of tags on the image.");
|
||||
assertThat(testImage.repoTags()).contains(toTag(IMAGE_REPOSITORY, IMAGE_TAG_1),
|
||||
toTag(IMAGE_REPOSITORY, IMAGE_TAG_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a node from the newly created image. The dropbear SSH server running
|
||||
* on custom port ( {@value #SSH_PORT}). The Docker networkMode used is
|
||||
* "host". Execute a command through the SSH connection and check the result.
|
||||
* Destroy the node when finished.
|
||||
*
|
||||
* @throws RunNodesException
|
||||
*/
|
||||
@Test(dependsOnMethods = "testImageCreated")
|
||||
public void testCustomPortSsh() throws RunNodesException {
|
||||
final DockerTemplateOptions options = DockerTemplateOptions.Builder
|
||||
.env("SSH_PORT=" + SSH_PORT, "ROOT_PASSWORD=screencast")
|
||||
.overrideLoginUser("root").overrideLoginPassword("screencast")
|
||||
.blockOnPort(SSH_PORT, 30).networkMode("host");
|
||||
|
||||
final Template template = view.getComputeService().templateBuilder().imageId(image.id()).options(options).build();
|
||||
|
||||
String nodeId = null;
|
||||
try {
|
||||
NodeMetadata node = Iterables
|
||||
.getOnlyElement(view.getComputeService().createNodesInGroup("ssh-net-host", 1, template));
|
||||
|
||||
nodeId = node.getId();
|
||||
ExecResponse response = view.getComputeService().runScriptOnNode(nodeId, "sh -c 'echo hello && sleep 0.2'", wrapInInitScript(false));
|
||||
assertThat(response.getOutput().trim()).endsWith("hello");
|
||||
} finally {
|
||||
if (nodeId != null)
|
||||
view.getComputeService().destroyNode(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dependsOnMethods = "testImageCreated")
|
||||
public void testAdvancedConfig() throws RunNodesException {
|
||||
final String portId = SSH_PORT + "/tcp";
|
||||
final DockerTemplateOptions options = DockerTemplateOptions.Builder
|
||||
.configBuilder(
|
||||
Config.builder().env(ImmutableList.<String> of("SSH_PORT=" + SSH_PORT, "ROOT_PASSWORD=jcloudsRulez"))
|
||||
.exposedPorts(ImmutableMap.<String, Object> of(portId, Maps.newHashMap()))
|
||||
.hostConfig(HostConfig.builder().networkMode("bridge")
|
||||
.portBindings(ImmutableMap.<String, List<Map<String, String>>> of(portId,
|
||||
Lists.<Map<String, String>>newArrayList(ImmutableMap.of("HostPort", String.valueOf(SSH_PORT_BRIDGE)))))
|
||||
.build())
|
||||
.image("test-if-this-value-is-correctly-overriden"))
|
||||
.overrideLoginUser("root").overrideLoginPassword("jcloudsRulez").blockOnPort(SSH_PORT_BRIDGE, 30);
|
||||
|
||||
final Template template = view.getComputeService().templateBuilder().imageId(image.id()).options(options).build();
|
||||
|
||||
String nodeId = null;
|
||||
try {
|
||||
NodeMetadata node = Iterables
|
||||
.getOnlyElement(view.getComputeService().createNodesInGroup("ssh-net-bridge", 1, template));
|
||||
|
||||
nodeId = node.getId();
|
||||
ExecResponse response = view.getComputeService().runScriptOnNode(nodeId, "sh -c 'true'",
|
||||
wrapInInitScript(false));
|
||||
assertEquals(response.getExitStatus(), 0);
|
||||
} finally {
|
||||
if (nodeId != null)
|
||||
view.getComputeService().destroyNode(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new image with 2 tags on it in the test preparation phase.
|
||||
*
|
||||
* @see org.jclouds.apis.BaseContextLiveTest#setupContext()
|
||||
*/
|
||||
@Override
|
||||
@BeforeClass(groups = { "integration", "live" })
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
final String tag = toTag(IMAGE_REPOSITORY, IMAGE_TAG_1);
|
||||
|
||||
removeImageIfExists(api(), tag);
|
||||
removeImageIfExists(api(), toTag(IMAGE_REPOSITORY, IMAGE_TAG_2));
|
||||
|
||||
BuildOptions options = BuildOptions.Builder.tag(tag).verbose(false).nocache(false);
|
||||
InputStream buildImageStream;
|
||||
try {
|
||||
buildImageStream = api().getMiscApi().build(BaseDockerApiLiveTest.tarredDockerfile(), options);
|
||||
consumeStreamSilently(buildImageStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error occured during building Docker image.", e);
|
||||
}
|
||||
image = api().getImageApi().inspectImage(tag);
|
||||
api().getImageApi().tagImage(image.id(), IMAGE_REPOSITORY, IMAGE_TAG_2, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* After the test remove created image (with all tags).
|
||||
*
|
||||
* @see #setupContext()
|
||||
*/
|
||||
@AfterClass(alwaysRun = true)
|
||||
protected void tearDown() {
|
||||
removeImageIfExists(api(), toTag(IMAGE_REPOSITORY, IMAGE_TAG_1));
|
||||
removeImageIfExists(api(), toTag(IMAGE_REPOSITORY, IMAGE_TAG_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure used modules. A custom {@link LoginPortForContainer} binding is
|
||||
* added among logging and SSH module.
|
||||
*
|
||||
* @see org.jclouds.compute.internal.BaseGenericComputeServiceContextLiveTest#setupModules()
|
||||
*/
|
||||
@Override
|
||||
protected Iterable<Module> setupModules() {
|
||||
return ImmutableSet.<Module> of(getLoggingModule(), new SshjSshClientModule(), new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(LoginPortForContainer.class).toInstance(new LoginPortForContainer() {
|
||||
@Override
|
||||
public Optional<Integer> apply(Container container) {
|
||||
return Optional.of(container.name().contains("ssh-net-bridge") ? SSH_PORT_BRIDGE : SSH_PORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return DockerApi for current Context.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private DockerApi api() {
|
||||
return view.unwrapApi(DockerApi.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate repository and tag name (if provided) in Docker format.
|
||||
*
|
||||
* @param repo
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
private static String toTag(String repo, String tag) {
|
||||
return repo + (tag != null ? ":" + tag : "");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* 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 org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
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.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.NetworkSettings;
|
||||
import org.jclouds.docker.domain.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.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"))
|
||||
.image("jclouds/ubuntu")
|
||||
.workingDir("")
|
||||
.entrypoint(null)
|
||||
.networkDisabled(false)
|
||||
.build();
|
||||
State state = State.create( //
|
||||
3626, // pid
|
||||
true, // running
|
||||
0, // exitCode
|
||||
"2014-03-24T20:28:37.537659054Z", // startedAt
|
||||
"0001-01-01T00:00:00Z", // finishedAt
|
||||
false, // paused
|
||||
false, // restarting
|
||||
"running", // Status
|
||||
false, // OOMKilled
|
||||
false, // Dead
|
||||
"" // Error
|
||||
);
|
||||
container = Container.builder()
|
||||
.id("6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9")
|
||||
.name("/hopeful_mclean")
|
||||
.created(new SimpleDateFormatDateService().iso8601DateParse("2014-03-22T07:16:45.784120972Z"))
|
||||
.path("/usr/sbin/sshd")
|
||||
.args(Arrays.asList("-D"))
|
||||
.config(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())
|
||||
.node(null)
|
||||
.build();
|
||||
ProviderMetadata providerMetadata = EasyMock.createMock(ProviderMetadata.class);
|
||||
expect(providerMetadata.getEndpoint()).andReturn("http://127.0.0.1:4243").atLeastOnce();
|
||||
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, new StateToStatus(), namingConvention, images, locations,
|
||||
new LoginPortForContainer.LoginPortLookupChain(null));
|
||||
}
|
||||
|
||||
public void testVirtualMachineToNodeMetadata() {
|
||||
NodeMetadata node = function.apply(container);
|
||||
|
||||
assertEquals(node.getId(), "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9");
|
||||
assertEquals(node.getGroup(), "hopeful_mclean");
|
||||
assertEquals(node.getImageId(), "af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6");
|
||||
assertEquals(node.getLoginPort(), 49199);
|
||||
assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
|
||||
assertEquals(node.getImageId(), "af0f59f1c19eef9471c3b8c8d587c39b8f130560b54f3766931b37d76d5de4b6");
|
||||
assertEquals(node.getPrivateAddresses(), ImmutableSet.of("172.17.0.2"));
|
||||
assertEquals(node.getPublicAddresses(), ImmutableSet.of("127.0.0.1"));
|
||||
}
|
||||
|
||||
public void testVirtualMachineWithNetworksToNodeMetadata() {
|
||||
// Example networks taken from container.json
|
||||
Container containerWithNetwork = container.toBuilder()
|
||||
.networkSettings(container.networkSettings().toBuilder()
|
||||
.networks(ImmutableMap.<String, NetworkSettings.Details>builder()
|
||||
.put("JCLOUDS_NETWORK", NetworkSettings.Details.builder()
|
||||
.endpoint("1a10519f808faf1181cfdf3d1d6dd93e19ede2d1c8fed82562a4c17c297c4db3")
|
||||
.gateway("172.19.0.1")
|
||||
.ipAddress("172.19.0.2")
|
||||
.ipPrefixLen(16)
|
||||
.ipv6Gateway("")
|
||||
.globalIPv6Address("")
|
||||
.globalIPv6PrefixLen(0)
|
||||
.macAddress("02:42:ac:13:00:02")
|
||||
.build())
|
||||
.put("bridge", NetworkSettings.Details.builder()
|
||||
.endpoint("9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6")
|
||||
.gateway("172.17.0.1")
|
||||
.ipAddress("172.17.0.2")
|
||||
.ipPrefixLen(16)
|
||||
.ipv6Gateway("")
|
||||
.globalIPv6Address("")
|
||||
.globalIPv6PrefixLen(0)
|
||||
.macAddress("02:42:ac:11:00:02")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
NodeMetadata node = function.apply(containerWithNetwork);
|
||||
|
||||
// Only asserting network-related aspects; the rest is covered by testVirtualMachineToNodeMetadata
|
||||
assertEquals(node.getLoginPort(), 49199);
|
||||
assertEquals(node.getPrivateAddresses(), ImmutableSet.of("172.17.0.2", "172.19.0.2"));
|
||||
assertEquals(node.getPublicAddresses(), ImmutableSet.of("127.0.0.1"));
|
||||
}
|
||||
}
|
|
@ -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.compute.functions;
|
||||
|
||||
import static org.jclouds.docker.compute.config.LoginPortLookupModule.loginPortLookupBinder;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.docker.compute.config.LoginPortLookupModule;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class CustomLoginPortFromImageTest {
|
||||
|
||||
private CustomLoginPortFromImage customLoginPortFromImage;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() {
|
||||
Injector i = Guice.createInjector(new LoginPortLookupModule(), new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
MapBinder<String, LoginPortForContainer> imageToFunction = loginPortLookupBinder(binder());
|
||||
imageToFunction.addBinding(".*alpine-ext.*").toInstance(LoginPortFromEnvVar);
|
||||
imageToFunction.addBinding(".*ubuntu.*").toInstance(AlwaysPort22);
|
||||
imageToFunction.addBinding(".*ubuntu:12\\.04.*").toInstance(AlwaysPort8080);
|
||||
}
|
||||
});
|
||||
customLoginPortFromImage = i.getInstance(CustomLoginPortFromImage.class);
|
||||
}
|
||||
|
||||
public void testPortFromEnvironmentVariables() {
|
||||
Config config = Config.builder().image("alpine-ext:3.2").env(ImmutableList.of("FOO=bar", "SSH_PORT=2345"))
|
||||
.build();
|
||||
Container container = Container.builder().id("id").config(config).build();
|
||||
|
||||
assertEquals(customLoginPortFromImage.apply(container).get().intValue(), 2345);
|
||||
}
|
||||
|
||||
public void testMostSpecificImageIsPicked() {
|
||||
Config config = Config.builder().image("ubuntu:12.04").build();
|
||||
Container container = Container.builder().id("id").config(config).build();
|
||||
|
||||
assertEquals(customLoginPortFromImage.apply(container).get().intValue(), 8080);
|
||||
}
|
||||
|
||||
public void testNoImageFoundInMap() {
|
||||
Config config = Config.builder().image("unexisting").build();
|
||||
Container container = Container.builder().id("id").config(config).build();
|
||||
|
||||
assertEquals(customLoginPortFromImage.apply(container), Optional.absent());
|
||||
}
|
||||
|
||||
private static final LoginPortForContainer LoginPortFromEnvVar = new LoginPortForContainer() {
|
||||
@Override
|
||||
public Optional<Integer> apply(Container input) {
|
||||
Optional<String> portVariable = Iterables.tryFind(input.config().env(), new Predicate<String>() {
|
||||
@Override
|
||||
public boolean apply(String input) {
|
||||
String[] var = input.split("=");
|
||||
return var[0].equals("SSH_PORT");
|
||||
}
|
||||
});
|
||||
return portVariable.isPresent() ? Optional.of(Integer.valueOf(portVariable.get().split("=")[1])) : Optional
|
||||
.<Integer> absent();
|
||||
}
|
||||
};
|
||||
|
||||
private static final LoginPortForContainer AlwaysPort22 = new LoginPortForContainer() {
|
||||
@Override
|
||||
public Optional<Integer> apply(Container input) {
|
||||
return Optional.of(22);
|
||||
}
|
||||
};
|
||||
|
||||
private static final LoginPortForContainer AlwaysPort8080 = new LoginPortForContainer() {
|
||||
@Override
|
||||
public Optional<Integer> apply(Container input) {
|
||||
return Optional.of(8080);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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 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.Date;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
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 static final org.jclouds.docker.domain.Image IMAGE_EMPTY_REPOTAGS = org.jclouds.docker.domain.Image.create(
|
||||
"id", // id
|
||||
"author",
|
||||
"comment",
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.<String> of() // repoTags
|
||||
);
|
||||
|
||||
private static final org.jclouds.docker.domain.Image IMAGE_REPOTAG_WITH_PORT = org.jclouds.docker.domain.Image.create(
|
||||
"id", // id
|
||||
"author",
|
||||
"comment",
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.of("registry.company.example:8888/a/b/c/d:latest") // repoTags
|
||||
);
|
||||
|
||||
private ImageToImage function;
|
||||
|
||||
private org.jclouds.docker.domain.Image image;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() {
|
||||
image = org.jclouds.docker.domain.Image.create(
|
||||
"id", // id
|
||||
"author",
|
||||
"comment",
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
Config.builder()
|
||||
.image("imageId")
|
||||
.build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.of("repoTag1:version") // repoTags
|
||||
);
|
||||
function = new ImageToImage();
|
||||
}
|
||||
|
||||
public void testImageToImage() {
|
||||
org.jclouds.docker.domain.Image mockImage = mockImage();
|
||||
|
||||
Image image = function.apply(mockImage);
|
||||
|
||||
verify(mockImage);
|
||||
|
||||
assertEquals(mockImage.id(), image.getId().toString());
|
||||
}
|
||||
|
||||
public void testEmptyRepoTags() {
|
||||
Image image = function.apply(IMAGE_EMPTY_REPOTAGS);
|
||||
|
||||
assertEquals(image.getId(), "id");
|
||||
assertEquals(image.getDescription(), "<none>");
|
||||
assertEquals(image.getOperatingSystem().getVersion(), "<none>");
|
||||
assertEquals(image.getName(), "<none>");
|
||||
}
|
||||
|
||||
public void testRepoTagWithHostPort() {
|
||||
Image image = function.apply(IMAGE_REPOTAG_WITH_PORT);
|
||||
|
||||
assertEquals(image.getDescription(), "registry.company.example:8888/a/b/c/d:latest");
|
||||
assertEquals(image.getOperatingSystem().getVersion(), "latest");
|
||||
assertEquals(image.getName(), "registry.company.example:8888/a/b/c/d");
|
||||
}
|
||||
|
||||
private org.jclouds.docker.domain.Image mockImage() {
|
||||
org.jclouds.docker.domain.Image mockImage = EasyMock.createMock(org.jclouds.docker.domain.Image.class);
|
||||
|
||||
expect(mockImage.id()).andReturn(image.id()).anyTimes();
|
||||
expect(mockImage.repoTags()).andReturn(image.repoTags()).anyTimes();
|
||||
expect(mockImage.architecture()).andReturn(image.architecture()).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
|
||||
* 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 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.running(), true);
|
||||
assertEquals(status, NodeMetadata.Status.RUNNING);
|
||||
}
|
||||
|
||||
public void testStateNotRunningToStatusTerminated() {
|
||||
State mockState = mockStateNotRunning();
|
||||
|
||||
NodeMetadata.Status status = function.apply(mockState);
|
||||
|
||||
verify(mockState);
|
||||
|
||||
assertEquals(mockState.running(), false);
|
||||
assertEquals(status, NodeMetadata.Status.TERMINATED);
|
||||
}
|
||||
|
||||
private State mockStateRunning() {
|
||||
State mockState = EasyMock.createMock(State.class);
|
||||
|
||||
expect(mockState.running()).andReturn(true).anyTimes();
|
||||
replay(mockState);
|
||||
|
||||
return mockState;
|
||||
}
|
||||
|
||||
private State mockStateNotRunning() {
|
||||
State mockState = EasyMock.createMock(State.class);
|
||||
|
||||
expect(mockState.running()).andReturn(false).anyTimes();
|
||||
replay(mockState);
|
||||
|
||||
return mockState;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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 static org.testng.Assert.assertNotNull;
|
||||
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Config.Builder;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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 = DockerTemplateOptions.Builder.hostname("hostname");
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getHostname(), "hostname");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemory() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.memory(1024);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getMemory(), Integer.valueOf(1024));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpuShares() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.cpuShares(2);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getCpuShares(), Integer.valueOf(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVolumes() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.volumes(ImmutableMap.of("/tmp", "/tmp"));
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getVolumes(), ImmutableMap.of("/tmp", "/tmp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDns() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.dns("8.8.8.8", "8.8.4.4");
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getDns(), ImmutableList.of("8.8.8.8", "8.8.4.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntrypoint() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.entrypoint("/bin/sh", "-c");
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getEntrypoint(), ImmutableList.of("/bin/sh", "-c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommands() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.commands("chmod 666 /etc/*", "rm -rf /var/run");
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getCommands(), ImmutableList.of("chmod 666 /etc/*", "rm -rf /var/run"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnv() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.env(ImmutableList.of("HOST=abc", "PORT=1234"));
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getEnv(), ImmutableList.of("HOST=abc", "PORT=1234"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPortBindings() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.portBindings(ImmutableMap.<Integer, Integer>builder().put(8443, 443).put(8080, 80).build());
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getPortBindings(), ImmutableMap.<Integer, Integer>builder().put(8443, 443).put(8080, 80).build());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNetworkMode() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.networkMode("host");
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getNetworkMode(), "host");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrivilegedDefaultFalse() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.memory(2);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getPrivileged(), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrivileged() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.privileged(true);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getPrivileged(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigBuilder() {
|
||||
Builder builder = Config.builder().memory(1024)
|
||||
.cpuShares(100).cmd(ImmutableList.<String> of("/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0"))
|
||||
.env(ImmutableList.<String> of("JAVA_HOME=/opt/jdk-1.8", "MGMT_USER=admin",
|
||||
"MGMT_PASSWORD=Schroedinger's Cat"));
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.configBuilder(builder);
|
||||
Builder builderInOpts = options.as(DockerTemplateOptions.class).getConfigBuilder();
|
||||
assertNotNull(builderInOpts);
|
||||
Config configFromOptions = builderInOpts.build();
|
||||
assertEquals(configFromOptions, builder.build());
|
||||
assertEquals(configFromOptions.env(), ImmutableList.<String> of("JAVA_HOME=/opt/jdk-1.8", "MGMT_USER=admin",
|
||||
"MGMT_PASSWORD=Schroedinger's Cat"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonDockerOptions() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.userMetadata(ImmutableMap.of("key", "value")).cpuShares(1);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getUserMetadata(), ImmutableMap.of("key", "value"));
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getCpuShares(), Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleOptions() {
|
||||
TemplateOptions options = DockerTemplateOptions.Builder.memory(512).cpuShares(4);
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getMemory(), Integer.valueOf(512));
|
||||
assertEquals(options.as(DockerTemplateOptions.class).getCpuShares(), Integer.valueOf(4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyTo() {
|
||||
DockerTemplateOptions options = DockerTemplateOptions.Builder
|
||||
.memory(512)
|
||||
.cpuShares(4)
|
||||
.entrypoint("entry", "point")
|
||||
.commands("test", "abc")
|
||||
.portBindings(
|
||||
ImmutableMap.<Integer, Integer> builder()
|
||||
.put(8443, 443).build())
|
||||
.hostname("hostname")
|
||||
.networkMode("host")
|
||||
.userMetadata(ImmutableMap.of("key", "value"))
|
||||
.env(ImmutableList.of("HOST=abc", "PORT=1234"))
|
||||
.dns("8.8.8.8", "8.8.4.4")
|
||||
.volumes(ImmutableMap.of("/tmp", "/tmp"));
|
||||
DockerTemplateOptions optionsCopy = new DockerTemplateOptions();
|
||||
options.copyTo(optionsCopy);
|
||||
assertEquals(optionsCopy, options);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Unit tests for finding images logic used in
|
||||
* {@link DockerComputeServiceAdapter#getImage(String)} method. It's mainly a
|
||||
* regression test for issue
|
||||
* <a href="https://issues.apache.org/jira/browse/JCLOUDS-1158">JCLOUDS-1158</a>
|
||||
* .
|
||||
*/
|
||||
@Test(groups = "unit", testName = "PredicateLocateImageByNameTest")
|
||||
public class PredicateLocateImageByNameTest {
|
||||
|
||||
private static final Image IMAGE_REPO_TAGS_MULTI = Image.create("id", // id
|
||||
"author", "comment", Config.builder().image("imageId").build(), Config.builder().image("imageId").build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.<String> of("kwart/alpine-ext:3.3-ssh", "kwart/alpine-ext:latest", "my-tag:latestdock") // repoTags
|
||||
);
|
||||
|
||||
private static final Image IMAGE_REPO_TAGS_EMPTY = Image.create("id", // id
|
||||
"author", "comment", Config.builder().image("imageId").build(), Config.builder().image("imageId").build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.<String> of() // repoTags
|
||||
);
|
||||
|
||||
private static final Image IMAGE_REPO_TAGS_WITH_HOST = Image.create("id", // id
|
||||
"author", "comment", Config.builder().image("imageId").build(), Config.builder().image("imageId").build(),
|
||||
"parent", // parent
|
||||
new Date(), // created
|
||||
"containerId", // container
|
||||
"1.3.1", // dockerVersion
|
||||
"x86_64", // architecture
|
||||
"os", // os
|
||||
0l, // size
|
||||
0l, // virtualSize
|
||||
ImmutableList.<String> of("docker.io/kwart/alpine-ext:3.3-ssh", "docker.io/kwart/alpine-ext:latest") // repoTags
|
||||
);
|
||||
|
||||
public void testRepoTagVersion() {
|
||||
final Predicate<Image> predicate = DockerComputeServiceAdapter
|
||||
.createPredicateMatchingRepoTags("kwart/alpine-ext:3.3-ssh");
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_MULTI));
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_EMPTY));
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_WITH_HOST));
|
||||
}
|
||||
|
||||
public void testRepoTagLatest() {
|
||||
final Predicate<Image> predicate = DockerComputeServiceAdapter.createPredicateMatchingRepoTags("kwart/alpine-ext");
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_MULTI));
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_EMPTY));
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_WITH_HOST));
|
||||
}
|
||||
|
||||
public void testRepoTagVersionWithHost() {
|
||||
final Predicate<Image> predicate = DockerComputeServiceAdapter
|
||||
.createPredicateMatchingRepoTags("docker.io/kwart/alpine-ext:3.3-ssh");
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_MULTI));
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_EMPTY));
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_WITH_HOST));
|
||||
}
|
||||
|
||||
public void testRepoTagLatestWithHost() {
|
||||
final Predicate<Image> predicate = DockerComputeServiceAdapter
|
||||
.createPredicateMatchingRepoTags("docker.io/kwart/alpine-ext");
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_MULTI));
|
||||
assertFalse(predicate.apply(IMAGE_REPO_TAGS_EMPTY));
|
||||
assertTrue(predicate.apply(IMAGE_REPO_TAGS_WITH_HOST));
|
||||
}
|
||||
|
||||
}
|
|
@ -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.config;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.NetworkSettings;
|
||||
import org.jclouds.docker.domain.Port;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.Guice;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link org.jclouds.docker.config.DockerParserModule} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "DockerParserModuleTest")
|
||||
public class DockerParserModuleTest {
|
||||
|
||||
private Json json = Guice.createInjector(new GsonModule(), new DockerParserModule()).getInstance(Json.class);
|
||||
|
||||
public void testContainerWithVolumesNull() {
|
||||
Container container = json.fromJson("{ \"Id\": \"foo\", \"Volumes\": null }", Container.class);
|
||||
assertNotNull(container);
|
||||
assertEquals(container.id(), "foo");
|
||||
assertEquals(container.volumes(), ImmutableMap.of());
|
||||
}
|
||||
|
||||
public void port() {
|
||||
// Note IP, not Ip
|
||||
String text = "{\"IP\":\"0.0.0.0\",\"PrivatePort\":4567,\"PublicPort\":49155,\"Type\":\"tcp\"}";
|
||||
Port port = Port.create("0.0.0.0", 4567, 49155, "tcp");
|
||||
assertEquals(json.fromJson(text, Port.class), port);
|
||||
assertEquals(json.toJson(port), text);
|
||||
}
|
||||
|
||||
public void networkSettings() {
|
||||
String text = "{" +
|
||||
"\"Bridge\":\"\"," +
|
||||
"\"SandboxID\":\"3ef128b055eb9ef62a6a2c281d97a2dfde5f47947d490f1dd2a81612611d961f\"," +
|
||||
"\"HairpinMode\":false," +
|
||||
"\"LinkLocalIPv6Address\":\"\"," +
|
||||
"\"LinkLocalIPv6PrefixLen\":0," +
|
||||
"\"Ports\":{}," +
|
||||
"\"SandboxKey\":\"/var/run/docker/netns/3ef128b055eb\"," +
|
||||
"\"SecondaryIPAddresses\":[]," +
|
||||
"\"SecondaryIPv6Addresses\":[]," +
|
||||
"\"EndpointID\":\"9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6\"," +
|
||||
"\"Gateway\":\"172.17.0.1\"," +
|
||||
"\"GlobalIPv6Address\":\"\"," +
|
||||
"\"GlobalIPv6PrefixLen\":0," +
|
||||
"\"IPAddress\":\"172.17.0.2\"," +
|
||||
"\"IPPrefixLen\":16," +
|
||||
"\"IPv6Gateway\":\"\"," +
|
||||
"\"MacAddress\":\"02:42:ac:11:00:02\"," +
|
||||
"\"Networks\":{" +
|
||||
"\"bridge\":{" +
|
||||
"\"EndpointID\":\"9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6\"," +
|
||||
"\"Gateway\":\"172.17.0.1\"," +
|
||||
"\"IPAddress\":\"172.17.0.2\"," +
|
||||
"\"IPPrefixLen\":16," +
|
||||
"\"IPv6Gateway\":\"\"," +
|
||||
"\"GlobalIPv6Address\":\"\"," +
|
||||
"\"GlobalIPv6PrefixLen\":0," +
|
||||
"\"MacAddress\":\"02:42:ac:11:00:02\"" +
|
||||
"}" +
|
||||
"}" +
|
||||
"}";
|
||||
NetworkSettings settings = NetworkSettings.create(
|
||||
"", // Bridge
|
||||
"3ef128b055eb9ef62a6a2c281d97a2dfde5f47947d490f1dd2a81612611d961f", // SandboxID
|
||||
false, // HairpinMode
|
||||
"", // LinkLocalIPv6Address
|
||||
0, // LinkLocalIPv6PrefixLen
|
||||
ImmutableMap.<String, List<Map<String, String>>> of(), // Ports
|
||||
"/var/run/docker/netns/3ef128b055eb", // SandboxKey
|
||||
null, // SecondaryIPAddresses
|
||||
null, // SecondaryIPv6Addresses
|
||||
"9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6", // EndpointID
|
||||
"172.17.0.1", // Gateway
|
||||
"", // GlobalIPv6Address
|
||||
0, // GlobalIPv6PrefixLen
|
||||
"172.17.0.2", // IPAddress
|
||||
16, // IPPrefixLen
|
||||
"", // IPv6Gateway
|
||||
"02:42:ac:11:00:02", // MacAddress
|
||||
ImmutableMap.of(
|
||||
"bridge", NetworkSettings.Details.create(
|
||||
"9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6", // EndpointID
|
||||
"172.17.0.1", // Gateway
|
||||
"172.17.0.2", // IPAddress
|
||||
16, // IPPrefixLen
|
||||
"", // IPv6Gateway
|
||||
"", // GlobalIPv6Address
|
||||
0, // GlobalIPv6PrefixLen
|
||||
"02:42:ac:11:00:02" // MacAddress
|
||||
)
|
||||
),
|
||||
null // PortMapping
|
||||
);
|
||||
|
||||
assertEquals(json.fromJson(text, NetworkSettings.class), settings);
|
||||
assertEquals(json.toJson(settings), text);
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@Test(groups = "unit", testName = "ConfigTest")
|
||||
public class ConfigTest {
|
||||
|
||||
@Test
|
||||
public void testFromConfig() {
|
||||
Config origConfig = Config.builder()
|
||||
.hostname("6c9932f478bd")
|
||||
.env(ImmutableList.of("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"))
|
||||
.image("57e570db16baba1e8c0d6f3c15868ddb400f64ff76ec948e65c3ca3f15fb3587")
|
||||
.domainname("")
|
||||
.user("")
|
||||
.cmd(ImmutableList.of("-name", "7a:63:a2:39:7b:0f"))
|
||||
.entrypoint(ImmutableList.of("/home/weave/weaver", "-iface", "ethwe", "-wait", "5"))
|
||||
.image("zettio/weave")
|
||||
.workingDir("/home/weave")
|
||||
.exposedPorts(ImmutableMap.of("6783/tcp", ImmutableMap.of(), "6783/udp", ImmutableMap.of()))
|
||||
.build();
|
||||
Config newConfig = Config.builder().fromConfig(origConfig).build();
|
||||
assertThat(origConfig).isEqualTo(newConfig);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullValuesPropagation() {
|
||||
Config config = Config.builder()
|
||||
.image("zettio/weave")
|
||||
.build();
|
||||
|
||||
assertThat(config.cmd()).isNull();
|
||||
assertThat(config.entrypoint()).isNull();
|
||||
assertThat(config.env()).isNull();
|
||||
assertThat(config.hostname()).isNull();
|
||||
assertThat(config.domainname()).isNull();
|
||||
assertThat(config.workingDir()).isNull();
|
||||
assertThat(config.hostConfig()).isNull();
|
||||
}
|
||||
}
|
|
@ -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.domain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "unit", testName = "ContainerTest")
|
||||
public class ContainerTest {
|
||||
|
||||
@Test
|
||||
public void testFromContainer() {
|
||||
Container testContainer = Container.builder()
|
||||
.id("testcontainer")
|
||||
.build();
|
||||
|
||||
|
||||
Container newTestContainer = testContainer.toBuilder().build();
|
||||
assertThat(newTestContainer).isEqualTo(testContainer);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.Resource;
|
||||
import org.jclouds.docker.options.AttachOptions;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.docker.options.RemoveContainerOptions;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "live", testName = "RemoteApiLiveTest", singleThreaded = true)
|
||||
public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private Container container = null;
|
||||
protected Image image = null;
|
||||
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
if (api.getImageApi().inspectImage(ALPINE_IMAGE_TAG) == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(ALPINE_IMAGE_TAG);
|
||||
InputStream createImageStream = api.getImageApi().createImage(options);
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
image = api.getImageApi().inspectImage(ALPINE_IMAGE_TAG);
|
||||
assertNotNull(image);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
protected void tearDown() {
|
||||
if (container != null) {
|
||||
if (api.getContainerApi().inspectContainer(container.id()) != null) {
|
||||
api.getContainerApi().removeContainer(container.id(), RemoveContainerOptions.Builder.force(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateContainer() throws IOException, InterruptedException {
|
||||
Config containerConfig = Config.builder().image(image.id())
|
||||
.cmd(ImmutableList.of("/bin/sh", "-c", "touch hello; while true; do echo hello world; sleep 1; done"))
|
||||
.build();
|
||||
container = api().createContainer("testCreateContainer", containerConfig);
|
||||
assertNotNull(container);
|
||||
assertNotNull(container.id());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateContainer")
|
||||
public void testStartContainer() throws IOException, InterruptedException {
|
||||
api().startContainer(container.id());
|
||||
assertTrue(api().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testStartContainer")
|
||||
public void testAttachContainer() throws InterruptedException {
|
||||
// wait 2 seconds - give a container chance to echo the string
|
||||
Thread.sleep(2000L);
|
||||
|
||||
InputStream attachStream = api().attach(container.id(), AttachOptions.Builder.logs(true).stream(false).stdout(true));
|
||||
String stream = consumeStream(attachStream);
|
||||
assertThat(stream.trim()).contains("hello world");
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testAttachContainer")
|
||||
public void testCopyFileFromContainer() {
|
||||
InputStream tarredStream = api().copy(container.id(), Resource.create("hello"));
|
||||
assertNotNull(consumeStream(tarredStream));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCopyFileFromContainer")
|
||||
public void testPauseContainer() {
|
||||
api().pause(container.id());
|
||||
assertTrue(api().inspectContainer(container.id()).state().paused());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testPauseContainer")
|
||||
public void testUnpauseContainer() {
|
||||
api().unpause(container.id());
|
||||
assertFalse(api().inspectContainer(container.id()).state().paused());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testUnpauseContainer")
|
||||
public void testStopContainer() {
|
||||
api().stopContainer(container.id());
|
||||
assertFalse(api().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testStopContainer")
|
||||
public void testRestartContainer() {
|
||||
api().restart(container.id());
|
||||
assertTrue(api().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testRestartContainer")
|
||||
public void testWaitContainer() {
|
||||
api().stopContainer(container.id(), 1);
|
||||
assertEquals(api().wait(container.id()).statusCode(), 137);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testWaitContainer")
|
||||
public void testRemoveContainer() {
|
||||
api().removeContainer(container.id());
|
||||
assertNull(api().inspectContainer(container.id()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListContainers() {
|
||||
List<ContainerSummary> containerSummaries = api().listContainers(ListContainerOptions.Builder.all(true));
|
||||
for (ContainerSummary containerSummary : containerSummaries) {
|
||||
assertNotNull(containerSummary.id());
|
||||
assertNotNull(containerSummary.image());
|
||||
assertFalse(containerSummary.names().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private ContainerApi api() {
|
||||
return api.getContainerApi();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.config.DockerParserModule;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Resource;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.docker.parse.ContainerParseTest;
|
||||
import org.jclouds.docker.parse.ContainersParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link org.jclouds.docker.features.ContainerApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ContainerApiMockTest")
|
||||
public class ContainerApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
public void testListContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/containers.json")));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
assertEquals(api.listContainers(), new ContainersParseTest().expected());
|
||||
assertSent(server, "GET", "/containers/json");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testListNonexistentContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(404));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
assertEquals(api.listContainers(), ImmutableList.of());
|
||||
assertSent(server, "GET", "/containers/json");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeOut = 10000l)
|
||||
public void testListAllContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/containers.json")));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
assertEquals(api.listContainers(ListContainerOptions.Builder.all(true)), new ContainersParseTest().expected());
|
||||
assertSent(server, "GET", "/containers/json?all=true");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/container.json")));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getContainerApi();
|
||||
String containerId = "e475abdf3e139a5e1e158b38b6cb290a1bec856d39d5a951f015dfb8fcba7331";
|
||||
try {
|
||||
assertEquals(api.inspectContainer(containerId), new ContainerParseTest().expected());
|
||||
assertSent(server, "GET", "/containers/" + containerId + "/json");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/container-creation.json")));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
Config containerConfig = Config.builder()
|
||||
.cmd(ImmutableList.of("date"))
|
||||
.attachStdin(false)
|
||||
.attachStderr(true)
|
||||
.attachStdout(true)
|
||||
.tty(false)
|
||||
.image("base")
|
||||
.build();
|
||||
try {
|
||||
Container container = api.createContainer("test", containerConfig);
|
||||
assertSent(server, "POST", "/containers/create?name=test");
|
||||
assertNotNull(container);
|
||||
assertThat(container.id()).isEqualTo("c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testRemoveContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
String containerId = "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9";
|
||||
|
||||
try {
|
||||
api.removeContainer(containerId);
|
||||
assertSent(server, "DELETE", "/containers/" + containerId);
|
||||
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.startContainer("1");
|
||||
assertSent(server, "POST", "/containers/1/start");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testStopContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.stopContainer("1");
|
||||
assertSent(server, "POST", "/containers/1/stop");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testCommitContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(201));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.commit();
|
||||
assertSent(server, "POST", "/commit");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testPauseContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.pause("1");
|
||||
assertSent(server, "POST", "/containers/1/pause");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnpauseContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.unpause("1");
|
||||
assertSent(server, "POST", "/containers/1/unpause");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testAttachContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.attach("1");
|
||||
assertSent(server, "POST", "/containers/1/attach");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testWaitContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.wait("1");
|
||||
assertSent(server, "POST", "/containers/1/wait");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testRestartContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.restart("1");
|
||||
assertSent(server, "POST", "/containers/1/restart");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testKillContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.kill("1");
|
||||
assertSent(server, "POST", "/containers/1/kill");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCopyFileFromContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ContainerApi api = api(DockerApi.class, server.getUrl("/").toString()).getContainerApi();
|
||||
try {
|
||||
api.copy("1", Resource.create("test"));
|
||||
assertSent(server, "POST", "/containers/1/copy");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.ImageSummary;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "live", testName = "ImageApiLiveTest", singleThreaded = true)
|
||||
public class ImageApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private Image image;
|
||||
|
||||
@Test
|
||||
public void testCreateImage() {
|
||||
InputStream createImageStream = api().createImage(CreateImageOptions.Builder.fromImage(DEFAULT_IMAGE).tag(DEFAULT_TAG));
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateImage")
|
||||
public void testInspectImage() {
|
||||
image = api.getImageApi().inspectImage(String.format("%s:%s", DEFAULT_IMAGE, DEFAULT_TAG));
|
||||
assertNotNull(image);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testInspectImage")
|
||||
public void testTagImage() {
|
||||
api.getImageApi().tagImage(image.id(), "jclouds", "testTag", true);
|
||||
Image taggedImage = api.getImageApi().inspectImage("jclouds:testTag");
|
||||
assertEquals(taggedImage.id(), image.id(), "Newly added image tag should point to the same image ID.");
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testTagImage")
|
||||
public void testListImages() {
|
||||
List<ImageSummary> listImages = api().listImages();
|
||||
assertNotNull(listImages);
|
||||
|
||||
Iterables.find(listImages, new Predicate<ImageSummary>() {
|
||||
@Override
|
||||
public boolean apply(ImageSummary input) {
|
||||
return input.repoTags().contains("jclouds:testTag");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListImages", alwaysRun = true)
|
||||
public void testDeleteImage() {
|
||||
consumeStream(api().deleteImage(String.format("%s:%s", DEFAULT_IMAGE, DEFAULT_TAG)));
|
||||
assertNull(api().inspectImage(String.format("%s:%s", DEFAULT_IMAGE, DEFAULT_TAG)));
|
||||
|
||||
assertNotNull(api().inspectImage(image.id()), "Image should should still exist after removing original tag. There is a newly added tag referencing it.");
|
||||
consumeStream(api().deleteImage("jclouds:testTag"));
|
||||
assertNull(api().inspectImage("jclouds:testTag"));
|
||||
}
|
||||
|
||||
private ImageApi api() {
|
||||
return api.getImageApi();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.config.DockerParserModule;
|
||||
import org.jclouds.docker.domain.ImageHistory;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.parse.HistoryParseTest;
|
||||
import org.jclouds.docker.parse.ImageParseTest;
|
||||
import org.jclouds.docker.parse.ImagesParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link org.jclouds.docker.features.ImageApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ImageApiMockTest")
|
||||
public class ImageApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
public void testCreateImage() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
|
||||
try {
|
||||
api.createImage(CreateImageOptions.Builder.fromImage("base"));
|
||||
assertSent(server, "POST", "/images/create?fromImage=base");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetImage() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/image.json")));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getImageApi();
|
||||
try {
|
||||
String imageId = "cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456";
|
||||
assertEquals(api.inspectImage(imageId), new ImageParseTest().expected());
|
||||
assertSent(server, "GET", "/images/" + imageId + "/json");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testListImages() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/images.json")));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
|
||||
try {
|
||||
assertEquals(api.listImages(), new ImagesParseTest().expected());
|
||||
assertSent(server, "GET", "/images/json");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testTagImage() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(201));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
|
||||
try {
|
||||
api.tagImage("633fcd11259e8d6bccfbb59a4086b95b0d0fb44edfc3912000ef1f70e8a7bfc6", "jclouds", "testTag", true);
|
||||
assertSent(server, "POST",
|
||||
"/images/633fcd11259e8d6bccfbb59a4086b95b0d0fb44edfc3912000ef1f70e8a7bfc6/tag?repo=jclouds&tag=testTag&force=true");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteImage() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
|
||||
try {
|
||||
api.deleteImage("1");
|
||||
assertSent(server, "DELETE", "/images/1");
|
||||
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetHistory() throws Exception {
|
||||
MockWebServer server = mockWebServer(
|
||||
new MockResponse().setBody(payloadFromResource("/history.json")),
|
||||
new MockResponse().setBody(payloadFromResource("/history-apiver22.json")),
|
||||
new MockResponse().setResponseCode(404));
|
||||
ImageApi api = api(DockerApi.class, server.getUrl("/").toString()).getImageApi();
|
||||
try {
|
||||
assertEquals(api.getHistory("ubuntu"), new HistoryParseTest().expected());
|
||||
assertSent(server, "GET", "/images/ubuntu/history");
|
||||
|
||||
// Docker Engine 1.10 (REST API ver 22) doesn't return parent layer IDs
|
||||
assertEquals(api.getHistory("fcf9d588ee9ab46c5a888e67f892fac66e6396eb195a743e50c0c5f9a4710e66"),
|
||||
ImmutableList.of(
|
||||
ImageHistory.create("sha256:fcf9d588ee9ab46c5a888e67f892fac66e6396eb195a743e50c0c5f9a4710e66",
|
||||
1456304238,
|
||||
"",
|
||||
ImmutableList.of("registry.acme.com:8888/jboss-eap-test/eap-test:1.0-3"),
|
||||
188605160,
|
||||
""),
|
||||
ImageHistory.create("<missing>",
|
||||
1455838658,
|
||||
"",
|
||||
null,
|
||||
195019519,
|
||||
""),
|
||||
ImageHistory.create("<missing>",
|
||||
1455812978,
|
||||
"",
|
||||
null,
|
||||
203250948,
|
||||
"Imported from -")
|
||||
));
|
||||
assertSent(server, "GET", "/images/fcf9d588ee9ab46c5a888e67f892fac66e6396eb195a743e50c0c5f9a4710e66/history");
|
||||
|
||||
// check also if empty list is returned if the image is not found
|
||||
List<ImageHistory> historyList = api.getHistory("missing-image");
|
||||
assertNotNull(historyList);
|
||||
assertTrue(historyList.isEmpty());
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.assertj.core.api.Fail;
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Exec;
|
||||
import org.jclouds.docker.domain.ExecCreateParams;
|
||||
import org.jclouds.docker.domain.ExecInspect;
|
||||
import org.jclouds.docker.domain.ExecStartParams;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.RemoveContainerOptions;
|
||||
import org.jclouds.docker.util.DockerInputStream;
|
||||
import org.jclouds.docker.util.StdStreamData;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "live", testName = "MiscApiLiveTest", singleThreaded = true)
|
||||
public class MiscApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String IMAGE_TEST_TAG = "jclouds-test-test-build-image";
|
||||
|
||||
private static String imageId;
|
||||
|
||||
private Container container = null;
|
||||
private Image image = null;
|
||||
private Exec exec = null;
|
||||
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
if (api.getImageApi().inspectImage(ALPINE_IMAGE_TAG) == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(ALPINE_IMAGE_TAG);
|
||||
InputStream createImageStream = api.getImageApi().createImage(options);
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
image = api.getImageApi().inspectImage(ALPINE_IMAGE_TAG);
|
||||
assertNotNull(image);
|
||||
Config containerConfig = Config.builder().image(image.id())
|
||||
.cmd(ImmutableList.of("/bin/sh", "-c", "touch hello; while true; do echo hello world; sleep 1; done"))
|
||||
.build();
|
||||
container = api.getContainerApi().createContainer("miscApiTest", containerConfig);
|
||||
assertNotNull(container);
|
||||
api.getContainerApi().startContainer(container.id());
|
||||
assertTrue(api.getContainerApi().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
protected void tearDown() {
|
||||
if (container != null) {
|
||||
if (api.getContainerApi().inspectContainer(container.id()) != null) {
|
||||
api.getContainerApi().removeContainer(container.id(), RemoveContainerOptions.Builder.force(true));
|
||||
}
|
||||
}
|
||||
if (image != null) {
|
||||
api.getImageApi().deleteImage(ALPINE_IMAGE_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersion() {
|
||||
assertNotNull(api().getVersion().apiVersion());
|
||||
assertNotNull(api().getVersion().version());
|
||||
assertNotNull(api().getVersion().gitCommit());
|
||||
assertNotNull(api().getVersion().goVersion());
|
||||
assertNotNull(api().getVersion().kernelVersion());
|
||||
assertNotNull(api().getVersion().arch());
|
||||
assertNotNull(api().getVersion().os());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfo() {
|
||||
assertNotNull(api().getInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildImageFromDockerfile() throws IOException, InterruptedException, URISyntaxException {
|
||||
removeImageIfExists(IMAGE_TEST_TAG);
|
||||
BuildOptions options = BuildOptions.Builder.tag(IMAGE_TEST_TAG).verbose(false).nocache(true);
|
||||
InputStream buildImageStream = api().build(tarredDockerfile(), options);
|
||||
String buildStream = consumeStream(buildImageStream);
|
||||
try {
|
||||
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));
|
||||
imageId = rawImageId.substring(0, 11);
|
||||
assertNotNull(imageId);
|
||||
} finally {
|
||||
removeImageIfExists(IMAGE_TEST_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecCreate() {
|
||||
exec = api().execCreate(container.id(),
|
||||
ExecCreateParams.builder()
|
||||
.cmd(ImmutableList.<String> of("/bin/sh", "-c",
|
||||
"echo -n Standard >&1 && echo -n Error >&2 && exit 2"))
|
||||
.attachStderr(true).attachStdout(true).build());
|
||||
assertNotNull(exec);
|
||||
assertNotNull(exec.id());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testExecCreate")
|
||||
public void testExecStart() throws IOException {
|
||||
final ExecStartParams startParams = ExecStartParams.builder().detach(false).build();
|
||||
DockerInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new DockerInputStream(api().execStart(exec.id(), startParams));
|
||||
assertNotNull(inputStream);
|
||||
ByteArrayOutputStream baosOut = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream baosErr = new ByteArrayOutputStream();
|
||||
StdStreamData data = null;
|
||||
while (null != (data = inputStream.readStdStreamData())) {
|
||||
assertFalse(data.isTruncated());
|
||||
switch (data.getType()) {
|
||||
case OUT:
|
||||
baosOut.write(data.getPayload());
|
||||
break;
|
||||
case ERR:
|
||||
baosErr.write(data.getPayload());
|
||||
break;
|
||||
default:
|
||||
Fail.fail("Unexpected Stream type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEquals(baosOut.toString(), "Standard");
|
||||
assertEquals(baosErr.toString(), "Error");
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testExecStart")
|
||||
public void testExecInspect() throws IOException {
|
||||
ExecInspect execInspect = api().execInspect(exec.id());
|
||||
assertNotNull(execInspect);
|
||||
assertEquals(execInspect.id(), exec.id());
|
||||
assertEquals(execInspect.running(), false);
|
||||
assertEquals(execInspect.exitCode(), 2);
|
||||
}
|
||||
|
||||
private MiscApi api() {
|
||||
return api.getMiscApi();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.jclouds.docker.compute.BaseDockerApiLiveTest.tarredDockerfile;
|
||||
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 java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.config.DockerParserModule;
|
||||
import org.jclouds.docker.domain.Exec;
|
||||
import org.jclouds.docker.domain.ExecCreateParams;
|
||||
import org.jclouds.docker.domain.ExecInspect;
|
||||
import org.jclouds.docker.domain.ExecStartParams;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.parse.InfoParseTest;
|
||||
import org.jclouds.docker.parse.VersionParseTest;
|
||||
import org.jclouds.docker.util.DockerInputStream;
|
||||
import org.jclouds.docker.util.StdStreamData;
|
||||
import org.jclouds.docker.util.StdStreamData.StdStreamType;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import com.squareup.okhttp.mockwebserver.RecordedRequest;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link org.jclouds.docker.features.MiscApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "MiscApiMockTest")
|
||||
public class MiscApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
public void testGetVersion() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/version.json")));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
|
||||
try {
|
||||
assertEquals(api.getVersion(), new VersionParseTest().expected());
|
||||
assertSent(server, "GET", "/version");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetInfo() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/info.json")));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
|
||||
try {
|
||||
assertEquals(api.getInfo(), new InfoParseTest().expected());
|
||||
assertSent(server, "GET", "/info");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
|
||||
try {
|
||||
api.build(tarredDockerfile());
|
||||
RecordedRequest request = assertSent(server, "POST", "/build");
|
||||
assertDockerBuildHttpHeaders(request);
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildContainerUsingPayload() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString()).getMiscApi();
|
||||
File file = File.createTempFile("docker", "tmp");
|
||||
FileInputStream data = new FileInputStream(file);
|
||||
Payload payload = Payloads.newInputStreamPayload(data);
|
||||
payload.getContentMetadata().setContentLength(file.length());
|
||||
try {
|
||||
api.build(payload);
|
||||
RecordedRequest request = assertSent(server, "POST", "/build");
|
||||
assertDockerBuildHttpHeaders(request);
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testExecCreate() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/exec.json")));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getMiscApi();
|
||||
try {
|
||||
final String containerId = "a40d212a0a379de00426a1da2a8fd3fd20d5f74fd7c2dd42f6c93a6b1b0e6974";
|
||||
final ExecCreateParams execParams = ExecCreateParams.builder()
|
||||
.cmd(ImmutableList.<String> of("/bin/sh", "-c", "echo -n Standard >&1 && echo -n Error >&2"))
|
||||
.attachStderr(true).attachStdout(true).build();
|
||||
final Exec expectedExec = Exec.create("dbf45d296388032ebb9872edb75847f6655a72b4e9ab0d99ae1c75589c4ca957");
|
||||
assertEquals(api.execCreate(containerId, execParams), expectedExec);
|
||||
assertSent(server, "POST", "/containers/" + containerId + "/exec");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testExecStart() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/exec.start")));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getMiscApi();
|
||||
DockerInputStream dis = null;
|
||||
try {
|
||||
final String execId = "dbf45d296388032ebb9872edb75847f6655a72b4e9ab0d99ae1c75589c4ca957";
|
||||
final ExecStartParams startParams = ExecStartParams.builder().detach(false).build();
|
||||
dis = new DockerInputStream(api.execStart(execId, startParams));
|
||||
|
||||
final StdStreamData msg1 = dis.readStdStreamData();
|
||||
assertFalse(msg1.isTruncated());
|
||||
assertEquals(msg1.getPayload(), "Standard".getBytes(StandardCharsets.UTF_8));
|
||||
assertEquals(msg1.getType(), StdStreamType.OUT);
|
||||
|
||||
final StdStreamData msg2 = dis.readStdStreamData();
|
||||
assertFalse(msg2.isTruncated());
|
||||
assertEquals(msg2.getPayload(), "Error".getBytes(StandardCharsets.UTF_8));
|
||||
assertEquals(msg2.getType(), StdStreamType.ERR);
|
||||
|
||||
assertNull(dis.readStdStreamData());
|
||||
assertSent(server, "POST", "/exec/" + execId + "/start");
|
||||
} finally {
|
||||
if (dis != null) {
|
||||
dis.close();
|
||||
}
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testExecInspect() throws IOException, InterruptedException {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/execInspect.json")));
|
||||
MiscApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getMiscApi();
|
||||
final String expectedExecId = "fda1cf8064863fc0667c691c69793fdb7d0bd4a1fabb8250536abe5203e4208a";
|
||||
ExecInspect execInspect = api.execInspect(expectedExecId);
|
||||
assertNotNull(execInspect);
|
||||
assertEquals(execInspect.id(), expectedExecId);
|
||||
assertEquals(execInspect.running(), false);
|
||||
assertEquals(execInspect.exitCode(), 2);
|
||||
assertSent(server, "GET", "/exec/" + expectedExecId + "/json");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that correct values of HTTP headers are used in Docker build REST
|
||||
* API calls.
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
private void assertDockerBuildHttpHeaders(RecordedRequest request) {
|
||||
assertThat(request.getHeader("Connection")).isEqualTo("close");
|
||||
assertThat(request.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo("application/tar");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "live", testName = "NetworkApiLiveTest", singleThreaded = true)
|
||||
public class NetworkApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String NETWORK_NAME = "JCLOUDS_NETWORK";
|
||||
|
||||
private Network network = null;
|
||||
protected Image image = null;
|
||||
private Container container;
|
||||
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
|
||||
if (api.getImageApi().inspectImage(ALPINE_IMAGE_TAG) == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(ALPINE_IMAGE_TAG);
|
||||
InputStream createImageStream = api.getImageApi().createImage(options);
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
image = api.getImageApi().inspectImage(ALPINE_IMAGE_TAG);
|
||||
assertNotNull(image);
|
||||
|
||||
Config containerConfig = Config.builder().image(image.id())
|
||||
.cmd(ImmutableList.of("sh", "-c", "touch hello; while true; do echo hello world; sleep 1; done"))
|
||||
.build();
|
||||
container = api.getContainerApi().createContainer("jclouds-test-network", containerConfig);
|
||||
api.getContainerApi().startContainer(container.id());
|
||||
container = api.getContainerApi().inspectContainer(container.id());
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
protected void tearDown() {
|
||||
if (container != null) {
|
||||
api.getContainerApi().stopContainer(container.id());
|
||||
api.getContainerApi().removeContainer(container.id());
|
||||
}
|
||||
if (network != null) {
|
||||
api().removeNetwork(network.id());
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateNetwork() throws IOException, InterruptedException {
|
||||
network = api().createNetwork(Network.create(NETWORK_NAME, null, null, null, null, ImmutableMap.<String, Network.Details> of(), ImmutableMap.<String, String> of()));
|
||||
assertNotNull(network);
|
||||
assertNotNull(network.id());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateNetwork")
|
||||
public void testGetNetwork() {
|
||||
network = api().inspectNetwork(network.id());
|
||||
assertNotNull(network);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testGetNetwork")
|
||||
public void testAttachContainerToNetwork() {
|
||||
api().connectContainerToNetwork(network.id(), container.id());
|
||||
container = api.getContainerApi().inspectContainer(container.id());
|
||||
assertTrue(Iterables.any(container.networkSettings().networks().keySet(), Predicates.equalTo(network.name())));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testAttachContainerToNetwork")
|
||||
public void testDisconnectContainerFromNetwork() {
|
||||
api().disconnectContainerFromNetwork(network.id(), container.id());
|
||||
container = api.getContainerApi().inspectContainer(container.id());
|
||||
assertFalse(Iterables.any(container.networkSettings().networks().keySet(), Predicates.equalTo(network.name())));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateNetwork")
|
||||
public void testListNetworks() {
|
||||
List<Network> networks = api().listNetworks();
|
||||
for (Network network : networks) {
|
||||
assertNotNull(network.id());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testDisconnectContainerFromNetwork")
|
||||
public void testRemoveNetwork() {
|
||||
api().removeNetwork(network.id());
|
||||
assertNull(api().inspectNetwork(network.id()));
|
||||
network = null;
|
||||
}
|
||||
|
||||
private NetworkApi api() {
|
||||
return api.getNetworkApi();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.config.DockerParserModule;
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.parse.NetworkParseTest;
|
||||
import org.jclouds.docker.parse.NetworksParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link NetworkApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "NetworkApiMockTest")
|
||||
public class NetworkApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
public void testListNetworks() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/networks.json")));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
try {
|
||||
assertEquals(api.listNetworks(), new NetworksParseTest().expected());
|
||||
assertSent(server, "GET", "/networks");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testListNonexistentNetworks() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(404));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
try {
|
||||
assertEquals(api.listNetworks(), ImmutableList.of());
|
||||
assertSent(server, "GET", "/networks");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetNetwork() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/network.json")));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString(), new DockerParserModule()).getNetworkApi();
|
||||
String networkId = "b03d4cd15b76f8876110615cdeed15eadf77c9beb408d62f1687dcc69192cd6d";
|
||||
try {
|
||||
assertEquals(api.inspectNetwork(networkId), new NetworkParseTest().expected());
|
||||
assertSent(server, "GET", "/networks/" + networkId);
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateNetwork() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setBody(payloadFromResource("/network-creation.json")));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
|
||||
Map<String, String> options = ImmutableMap.<String, String> builder()
|
||||
.put("com.docker.network.bridge.default_bridge", "true")
|
||||
.put("com.docker.network.bridge.enable_icc", "true")
|
||||
.put("com.docker.network.bridge.enable_ip_masquerade", "true")
|
||||
.put("com.docker.network.bridge.host_binding_ipv4", "0.0.0.0")
|
||||
.put("com.docker.network.bridge.name", "docker0")
|
||||
.put("com.docker.network.driver.mtu", "1500")
|
||||
.build();
|
||||
|
||||
Network network = Network.create(
|
||||
"isolated_nw", // Name
|
||||
null, // Id
|
||||
"bridge", // Driver
|
||||
null, // Scope
|
||||
Network.IPAM.create(
|
||||
"default", // driver
|
||||
ImmutableList.of(Network.IPAM.Config.create("172.17.0.0/16", null, null)) // config
|
||||
),
|
||||
ImmutableMap.of("39b69226f9d79f5634485fb236a23b2fe4e96a0a94128390a7fbbcc167065867",
|
||||
Network.Details.create(
|
||||
"ed2419a97c1d9954d05b46e462e7002ea552f216e9b136b80a7db8d98b442eda", //endpointId
|
||||
"02:42:ac:11:00:02", // MAC
|
||||
"172.17.0.2/16", // ipv4address
|
||||
"" // ipv6address
|
||||
)
|
||||
),
|
||||
options);
|
||||
|
||||
try {
|
||||
Network created = api.createNetwork(network);
|
||||
assertNotNull(created);
|
||||
assertThat(created.id()).isEqualTo("22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30");
|
||||
assertSent(server, "POST", "/networks/create", "{\"Name\":\"isolated_nw\",\"Scope\":\"bridge\",\"IPAM\":{\"Driver\":\"default\",\"Config\":[{\"Subnet\":\"172.17.0.0/16\"}]},\"Containers\":{\"39b69226f9d79f5634485fb236a23b2fe4e96a0a94128390a7fbbcc167065867\":{\"EndpointID\":\"ed2419a97c1d9954d05b46e462e7002ea552f216e9b136b80a7db8d98b442eda\",\"MacAddress\":\"02:42:ac:11:00:02\",\"IPv4Address\":\"172.17.0.2/16\",\"IPv6Address\":\"\"}},\"Options\":{\"com.docker.network.bridge.default_bridge\":\"true\",\"com.docker.network.bridge.enable_icc\":\"true\",\"com.docker.network.bridge.enable_ip_masquerade\":\"true\",\"com.docker.network.bridge.host_binding_ipv4\":\"0.0.0.0\",\"com.docker.network.bridge.name\":\"docker0\",\"com.docker.network.driver.mtu\":\"1500\"}}");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testRemoveNetwork() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(204));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
String networkId = "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9";
|
||||
try {
|
||||
api.removeNetwork(networkId);
|
||||
assertSent(server, "DELETE", "/networks/" + networkId);
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testConnectContainerToNetwork() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
try {
|
||||
api.connectContainerToNetwork("123456789", "containerName");
|
||||
assertSent(server, "POST", "/networks/123456789/connect", "{ \"Container\": \"containerName\" }");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDisconnectContainerFromNetwork() throws Exception {
|
||||
MockWebServer server = mockWebServer(new MockResponse().setResponseCode(200));
|
||||
NetworkApi api = api(DockerApi.class, server.getUrl("/").toString()).getNetworkApi();
|
||||
try {
|
||||
api.disconnectContainerFromNetwork("123456789", "containerName");
|
||||
assertSent(server, "POST", "/networks/123456789/disconnect", "{ \"Container\": \"containerName\" }");
|
||||
} finally {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.base.Charsets.UTF_8;
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.jclouds.util.Strings2.toStringAndClose;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.http.BaseMockWebServerTest;
|
||||
import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.gson.JsonParser;
|
||||
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 extends BaseMockWebServerTest {
|
||||
|
||||
protected static final String API_VERSION = "1.15";
|
||||
|
||||
@Override
|
||||
protected void addOverrideProperties(Properties properties) {
|
||||
properties.setProperty("jclouds.api-version", API_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module createConnectionModule() {
|
||||
return new OkHttpCommandExecutorServiceModule();
|
||||
}
|
||||
|
||||
public byte[] payloadFromResource(String resource) {
|
||||
try {
|
||||
return toStringAndClose(getClass().getResourceAsStream(resource)).getBytes(Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected RecordedRequest assertSent(MockWebServer server, String method, String path) throws InterruptedException {
|
||||
RecordedRequest request = server.takeRequest();
|
||||
assertThat(request.getMethod()).isEqualTo(method);
|
||||
assertThat(request.getPath()).isEqualTo("/v" + API_VERSION + path);
|
||||
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON);
|
||||
return request;
|
||||
}
|
||||
|
||||
protected RecordedRequest assertSent(MockWebServer server, String method, String path, String json)
|
||||
throws InterruptedException {
|
||||
RecordedRequest request = assertSent(server, method, path);
|
||||
assertEquals(request.getHeader("Content-Type"), APPLICATION_JSON);
|
||||
assertEquals(parser.parse(new String(request.getBody(), UTF_8)), parser.parse(json));
|
||||
return request;
|
||||
}
|
||||
|
||||
/** So that we can ignore formatting. */
|
||||
private final JsonParser parser = new JsonParser();
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.internal;
|
||||
|
||||
import org.jclouds.docker.config.DockerParserModule;
|
||||
import org.jclouds.json.BaseItemParserTest;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
public abstract class BaseDockerParseTest<T> extends BaseItemParserTest<T> {
|
||||
|
||||
@Override
|
||||
protected Injector injector() {
|
||||
return Guice.createInjector(new GsonModule(), new DockerParserModule());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.features.ImageApi;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* Utility methods shared by Docker tests.
|
||||
*/
|
||||
public class DockerTestUtils {
|
||||
|
||||
/**
|
||||
* Read all data from given {@link InputStream} and throw away all the bits.
|
||||
* If an {@link IOException} occurs, it's not propagated to user. The given InputStream is closed after the read.
|
||||
*
|
||||
* @param is InputStream instance (may be null)
|
||||
*/
|
||||
public static void consumeStreamSilently(InputStream is) {
|
||||
if (is == null) {
|
||||
return;
|
||||
}
|
||||
char[] tmpBuff = new char[8 * 1024];
|
||||
// throw everything away
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
try {
|
||||
try {
|
||||
while (isr.read(tmpBuff) > -1) {
|
||||
// empty
|
||||
}
|
||||
} finally {
|
||||
isr.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
java.util.logging.Logger.getAnonymousLogger().log(Level.WARNING, "Error ocured during reading InputStream.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes Docker image if it's present on the Docker host. Docker Image API
|
||||
* is used to inspect and remove image (({@link ImageApi#deleteImage(String)}
|
||||
* method).
|
||||
*
|
||||
* @param dockerApi
|
||||
* DockerApi instance (must be not-<code>null</code>)
|
||||
* @param imageName
|
||||
* image to be deleted (must be not-<code>null</code>)
|
||||
*/
|
||||
public static void removeImageIfExists(DockerApi dockerApi, String imageName) {
|
||||
Preconditions.checkNotNull(dockerApi, "DockerApi instance has to be provided");
|
||||
Preconditions.checkNotNull(imageName, "Docker image name has to be provided");
|
||||
final ImageApi imageApi = dockerApi.getImageApi();
|
||||
if (null != imageApi.inspectImage(imageName)) {
|
||||
consumeStreamSilently(imageApi.deleteImage(imageName, DeleteImageOptions.Builder.force(true)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.NetworkSettings;
|
||||
import org.jclouds.docker.domain.Node;
|
||||
import org.jclouds.docker.domain.State;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ContainerParseTest extends BaseDockerParseTest<Container> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/container.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Container expected() {
|
||||
return Container.builder()
|
||||
.id("6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524")
|
||||
.created(new SimpleDateFormatDateService().iso8601DateParse("2014-10-31T17:00:21.544197943Z"))
|
||||
.path("/home/weave/weaver")
|
||||
.name("/weave")
|
||||
.args(ImmutableList.of("-iface", "ethwe", "-wait", "5", "-name", "7a:63:a2:39:7b:0f"))
|
||||
.config(Config.builder()
|
||||
.hostname("6c9932f478bd")
|
||||
.env(ImmutableList.of("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"))
|
||||
.image("zettio/weave")
|
||||
.domainname("")
|
||||
.user("")
|
||||
.cmd(ImmutableList.of("-name", "7a:63:a2:39:7b:0f"))
|
||||
.entrypoint(ImmutableList.of("/home/weave/weaver", "-iface", "ethwe", "-wait", "5"))
|
||||
.workingDir("/home/weave")
|
||||
.exposedPorts(ImmutableMap.of("6783/tcp", ImmutableMap.of(), "6783/udp", ImmutableMap.of()))
|
||||
.build())
|
||||
.state(State.create(10357, true, 0, "2015-11-10T09:33:21.68146124Z", "0001-01-01T00:00:00Z", false, false, "running", false, false, ""))
|
||||
.image("57e570db16baba1e8c0d6f3c15868ddb400f64ff76ec948e65c3ca3f15fb3587")
|
||||
.networkSettings(NetworkSettings.builder()
|
||||
.sandboxId("3ef128b055eb9ef62a6a2c281d97a2dfde5f47947d490f1dd2a81612611d961f")
|
||||
.hairpinMode(false)
|
||||
.linkLocalIPv6Address("")
|
||||
.linkLocalIPv6PrefixLen(0)
|
||||
.globalIPv6Address("")
|
||||
.globalIPv6PrefixLen(0)
|
||||
.ipv6Gateway("")
|
||||
.sandboxKey("/var/run/docker/netns/3ef128b055eb")
|
||||
.endpointId("9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6")
|
||||
.ipAddress("172.17.0.2")
|
||||
.ipPrefixLen(16)
|
||||
.gateway("172.17.0.1")
|
||||
.bridge("")
|
||||
.ports(ImmutableMap.<String, List<Map<String, String>>>of())
|
||||
.macAddress("02:42:ac:11:00:02")
|
||||
.networks(ImmutableMap.of(
|
||||
"JCLOUDS_NETWORK", NetworkSettings.Details.create(
|
||||
"04268fbb4dc368b5a53bb1c3f89294a4f0c72095deb944db3c4efc6d6a439304",
|
||||
"172.19.0.1",
|
||||
"172.19.0.2",
|
||||
16,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
"02:42:ac:13:00:02"
|
||||
),
|
||||
"bridge", NetworkSettings.Details.create(
|
||||
"9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6",
|
||||
"172.17.0.1",
|
||||
"172.17.0.2",
|
||||
16,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
"02:42:ac:11:00:02"
|
||||
)
|
||||
))
|
||||
.build())
|
||||
.resolvConfPath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/resolv.conf")
|
||||
.hostConfig(HostConfig.builder()
|
||||
.containerIDFile("")
|
||||
.portBindings(ImmutableMap.<String, List<Map<String, String>>>of(
|
||||
"6783/tcp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "", "HostPort", "6783")),
|
||||
"6783/udp", ImmutableList.<Map<String, String>>of(ImmutableMap.of("HostIp", "", "HostPort", "6783")))
|
||||
)
|
||||
.capAdd(ImmutableList.of("NET_ADMIN"))
|
||||
.capDrop(ImmutableList.of("MKNOD"))
|
||||
.dns(ImmutableList.of("8.8.8.8", "8.8.4.4"))
|
||||
.extraHosts(ImmutableList.<String>of("extra:169.254.0.1"))
|
||||
.privileged(true)
|
||||
.networkMode("bridge")
|
||||
.restartPolicy(ImmutableMap.<String, String> of("MaximumRetryCount", "0", "Name", ""))
|
||||
.build())
|
||||
.driver("aufs")
|
||||
.execDriver("native-0.2")
|
||||
.hostnamePath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hostname")
|
||||
.hostsPath("/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hosts")
|
||||
.mountLabel("")
|
||||
.processLabel("")
|
||||
.node(Node.builder().
|
||||
ip("10.10.10.10").build())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.NetworkSettings;
|
||||
import org.jclouds.docker.domain.State;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* This class tests Containers and Config parsing for Docker API in version 1.21. The input JSON comes from examples in
|
||||
* <a href="https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/">Docker Remote API documentation 1.21</a>.
|
||||
* <p>
|
||||
* Two modifications were made in the "/container-1.21-create.json" due to incompatible types
|
||||
* <ul>
|
||||
* <li>the Entrypoint field value was changed from String to List<li>
|
||||
* <li>the LxcConf field value was changed from Map to List</li>
|
||||
* <ul>
|
||||
*/
|
||||
public class ContainerVersionMajor1Minor21 {
|
||||
|
||||
@Test(groups = "unit")
|
||||
public static class CreateTest extends BaseDockerParseTest<Config> {
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/container-1.21-create.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Config expected() {
|
||||
return Config.builder()
|
||||
.hostname("")
|
||||
.domainname("")
|
||||
.user("")
|
||||
.attachStdin(false)
|
||||
.attachStdout(true)
|
||||
.attachStderr(true)
|
||||
.tty(false)
|
||||
.openStdin(false)
|
||||
.stdinOnce(false)
|
||||
.env(ImmutableList.of("FOO=bar", "BAZ=quux"))
|
||||
.cmd(ImmutableList.of("date"))
|
||||
//original value of the "Entrypoint" in JSON doesn't contain List but String!
|
||||
//Both types are allowed by docker Remote API, but we are not able to parse both.
|
||||
.entrypoint(ImmutableList.of(""))
|
||||
.image("ubuntu")
|
||||
// "Labels": {
|
||||
// "com.example.vendor": "Acme",
|
||||
// "com.example.license": "GPL",
|
||||
// "com.example.version": "1.0"
|
||||
// },
|
||||
.volumes(ImmutableMap.of("/volumes/data", ImmutableMap.of()))
|
||||
.workingDir("")
|
||||
.networkDisabled(false)
|
||||
// "MacAddress": "12:34:56:78:9a:bc",
|
||||
.exposedPorts(ImmutableMap.of("22/tcp", ImmutableMap.of()))
|
||||
// "StopSignal": "SIGTERM",
|
||||
.hostConfig(HostConfig.builder()
|
||||
.binds(ImmutableList.of("/tmp:/tmp"))
|
||||
.links(ImmutableList.of("redis3:redis"))
|
||||
//The LxcConf causes the type mismatch too (Map vs List<Map>)
|
||||
.lxcConf(ImmutableList.<Map<String, String>> of(
|
||||
ImmutableMap.<String, String> of("lxc.utsname", "docker")))
|
||||
// "Memory": 0,
|
||||
// "MemorySwap": 0,
|
||||
// "MemoryReservation": 0,
|
||||
// "KernelMemory": 0,
|
||||
// "CpuShares": 512,
|
||||
// "CpuPeriod": 100000,
|
||||
// "CpuQuota": 50000,
|
||||
// "CpusetCpus": "0,1",
|
||||
// "CpusetMems": "0,1",
|
||||
// "BlkioWeight": 300,
|
||||
// "MemorySwappiness": 60,
|
||||
// "OomKillDisable": false,
|
||||
.portBindings(ImmutableMap.<String, List<Map<String, String>>> of(
|
||||
"22/tcp", ImmutableList.<Map<String, String>> of(ImmutableMap.of("HostPort", "11022"))))
|
||||
.publishAllPorts(false)
|
||||
.privileged(false)
|
||||
// "ReadonlyRootfs": false,
|
||||
.dns(ImmutableList.of("8.8.8.8"))
|
||||
// "DnsOptions": [""],
|
||||
.dnsSearch(ImmutableList.of(""))
|
||||
.extraHosts(null)
|
||||
.volumesFrom(ImmutableList.of("parent", "other:ro"))
|
||||
.capAdd(ImmutableList.of("NET_ADMIN"))
|
||||
.capDrop(ImmutableList.of("MKNOD"))
|
||||
// "GroupAdd": ["newgroup"],
|
||||
.restartPolicy(ImmutableMap.of("Name", "", "MaximumRetryCount", "0"))
|
||||
.networkMode("bridge")
|
||||
// "Devices": [],
|
||||
// "Ulimits": [{}],
|
||||
// "LogConfig": { "Type": "json-file", "Config": {} },
|
||||
.securityOpt(ImmutableList.<String>of())
|
||||
// "CgroupParent": "",
|
||||
// "VolumeDriver": ""
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = "unit")
|
||||
public static class InspectTest extends BaseDockerParseTest<Container> {
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/container-1.21-inspect.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Container expected() {
|
||||
return Container.builder()
|
||||
// "AppArmorProfile": "",
|
||||
.args(ImmutableList.<String>of("-c", "exit 9"))
|
||||
.config(Config.builder()
|
||||
.attachStderr(true)
|
||||
.attachStdin(false)
|
||||
.attachStdout(true)
|
||||
.cmd(ImmutableList.<String> of("/bin/sh", "-c", "exit 9"))
|
||||
.domainname("")
|
||||
.entrypoint(null)
|
||||
.env(ImmutableList.<String> of("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"))
|
||||
.exposedPorts(null)
|
||||
.hostname("ba033ac44011")
|
||||
.image("ubuntu")
|
||||
// "Labels": {
|
||||
// "com.example.vendor": "Acme",
|
||||
// "com.example.license": "GPL",
|
||||
// "com.example.version": "1.0"
|
||||
// },
|
||||
// "MacAddress": "",
|
||||
.networkDisabled(false)
|
||||
// "OnBuild": null,
|
||||
.openStdin(false)
|
||||
.stdinOnce(false)
|
||||
.tty(false)
|
||||
.user("")
|
||||
.volumes(null)
|
||||
.workingDir("")
|
||||
// "StopSignal": "SIGTERM"
|
||||
.build())
|
||||
.created(new SimpleDateFormatDateService().iso8601DateParse("2015-01-06T15:47:31.485331387Z"))
|
||||
.driver("devicemapper")
|
||||
.execDriver("native-0.2")
|
||||
// "ExecIDs": null,
|
||||
.hostConfig(HostConfig.builder()
|
||||
.binds(null)
|
||||
// "BlkioWeight": 0,
|
||||
.capAdd(null)
|
||||
.capDrop(null)
|
||||
.containerIDFile("")
|
||||
// "CpusetCpus": "",
|
||||
// "CpusetMems": "",
|
||||
// "CpuShares": 0,
|
||||
// "CpuPeriod": 100000,
|
||||
// "Devices": [],
|
||||
.dns(null)
|
||||
// "DnsOptions": null,
|
||||
.dnsSearch(null)
|
||||
.extraHosts(null)
|
||||
// "IpcMode": "",
|
||||
.links(null)
|
||||
.lxcConf(ImmutableList.<Map<String, String>> of())
|
||||
// "Memory": 0,
|
||||
// "MemorySwap": 0,
|
||||
// "MemoryReservation": 0,
|
||||
// "KernelMemory": 0,
|
||||
// "OomKillDisable": false,
|
||||
.networkMode("bridge")
|
||||
.portBindings(ImmutableMap.<String, List<Map<String, String>>> of())
|
||||
.privileged(false)
|
||||
// "ReadonlyRootfs": false,
|
||||
.publishAllPorts(false)
|
||||
.restartPolicy(ImmutableMap.<String, String> of("MaximumRetryCount", "2", "Name", "on-failure"))
|
||||
// "LogConfig": {
|
||||
// "Config": null,
|
||||
// "Type": "json-file"
|
||||
// },
|
||||
.securityOpt(null)
|
||||
.volumesFrom(null)
|
||||
// "Ulimits": [{}],
|
||||
// "VolumeDriver": ""
|
||||
.build())
|
||||
.hostnamePath("/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname")
|
||||
.hostsPath("/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts")
|
||||
// "LogPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log",
|
||||
.id("ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39")
|
||||
.image("04c5d3b7b0656168630d3ba35d8889bd0e9caafcaeb3004d2bfbc47e7c5d35d2")
|
||||
.mountLabel("")
|
||||
.name("/boring_euclid")
|
||||
.networkSettings(NetworkSettings.builder()
|
||||
.bridge("")
|
||||
.sandboxId("")
|
||||
.hairpinMode(false)
|
||||
.linkLocalIPv6Address("")
|
||||
.linkLocalIPv6PrefixLen(0)
|
||||
.ports(null)
|
||||
.sandboxKey("")
|
||||
.secondaryIPAddresses(null)
|
||||
.secondaryIPv6Addresses(null)
|
||||
.endpointId("")
|
||||
.gateway("")
|
||||
.globalIPv6Address("")
|
||||
.globalIPv6PrefixLen(0)
|
||||
.ipAddress("")
|
||||
.ipPrefixLen(0)
|
||||
.ipv6Gateway("")
|
||||
.macAddress("")
|
||||
.networks(ImmutableMap.<String, NetworkSettings.Details> of(
|
||||
"bridge", NetworkSettings.Details.create("", "", "", 0, "", "", 0, "")))
|
||||
.build())
|
||||
.path("/bin/sh")
|
||||
.node(null)
|
||||
.processLabel("")
|
||||
.resolvConfPath("/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/resolv.conf")
|
||||
// "RestartCount": 1,
|
||||
.state(State.create(0, true, 9, "2015-01-06T15:47:32.072697474Z", "2015-01-06T15:47:32.080254511Z", false, false, "running", false,
|
||||
// We don't have the "Dead" field in this API version!
|
||||
false,
|
||||
""
|
||||
// "Paused": false,
|
||||
// "Running": true,
|
||||
))
|
||||
// "Mounts": [
|
||||
// {
|
||||
// "Source": "/data",
|
||||
// "Destination": "/data",
|
||||
// "Mode": "ro,Z",
|
||||
// "RW": false
|
||||
// }
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.Port;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ContainersParseTest extends BaseDockerParseTest<List<ContainerSummary>> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/containers.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public List<ContainerSummary> expected() {
|
||||
return ImmutableList.of(ContainerSummary.create(
|
||||
"6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9", ImmutableList.of("/hopeful_mclean"),
|
||||
"1395472605", "jclouds/ubuntu:latest", "/usr/sbin/sshd -D",
|
||||
ImmutableList.of(Port.create("0.0.0.0", 22, 49231, "tcp")), "Up 55 seconds"), ContainerSummary.create(
|
||||
"6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a2", ImmutableList.of("/hopeful_mclean"),
|
||||
"1395472605", "jclouds/ubuntu:latest", "/usr/sbin/sshd -D",
|
||||
ImmutableList.of(Port.create(null, 22, null, "tcp")), "Up 55 seconds"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.ImageHistory;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class HistoryParseTest extends BaseDockerParseTest<List<ImageHistory>> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/history.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public List<ImageHistory> expected() {
|
||||
return ImmutableList.of(
|
||||
ImageHistory.create("3db9c44f45209632d6050b35958829c3a2aa256d81b9a7be45b362ff85c54710",
|
||||
1398108230,
|
||||
"/bin/sh -c #(nop) ADD file:eb15dbd63394e063b805a3c32ca7bf0266ef64676d5a6fab4801f2e81e2a5148 in /",
|
||||
ImmutableList.of("ubuntu:lucid", "ubuntu:10.04"),
|
||||
182964289,
|
||||
""),
|
||||
ImageHistory.create("6cfa4d1f33fb861d4d114f43b25abd0ac737509268065cdfd69d544a59c85ab8",
|
||||
1398108222,
|
||||
"/bin/sh -c #(nop) MAINTAINER Tianon Gravi <admwiggin@gmail.com> - mkimage-debootstrap.sh -i iproute,iputils-ping,ubuntu-minimal -t lucid.tar.xz lucid http://archive.ubuntu.com/ubuntu/",
|
||||
null,
|
||||
0,
|
||||
""),
|
||||
ImageHistory.create("511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158",
|
||||
1371157430,
|
||||
"",
|
||||
ImmutableList.of("scratch12:latest", "scratch:latest"),
|
||||
0,
|
||||
"Imported from -")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.beust.jcommander.internal.Maps;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ImageParseTest extends BaseDockerParseTest<Image> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/image.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Image expected() {
|
||||
return Image.create("cbba6639a342646deed70d7ea6162fa2a0acea9300f911f4e014555fe37d3456",
|
||||
"author",
|
||||
"comment",
|
||||
Config.builder().cmd(ImmutableList.of("/bin/sh", "-c", "echo hello world"))
|
||||
.env(ImmutableList.of(
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"HOME=/root",
|
||||
"JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64"
|
||||
)
|
||||
)
|
||||
.exposedPorts(ImmutableMap.of("8081/tcp", Maps.newHashMap()))
|
||||
.hostname("f22711318734")
|
||||
.domainname("")
|
||||
.user("user")
|
||||
.image("05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba")
|
||||
.workingDir("/home/user")
|
||||
.build(),
|
||||
Config.builder().cmd(ImmutableList.of("/bin/sh", "-c", "echo hello world"))
|
||||
.env(ImmutableList.of(
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"HOME=/root",
|
||||
"JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64")
|
||||
)
|
||||
.exposedPorts(ImmutableMap.of("8081/tcp", Maps.newHashMap()))
|
||||
.hostname("f22711318734")
|
||||
.domainname("")
|
||||
.user("user")
|
||||
.image("05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba")
|
||||
.workingDir("/home/user")
|
||||
.build(),
|
||||
"05794515afd5724df1cdf0e674ae932455fce7dea3c70a94d77119ad1fa954ba",
|
||||
new SimpleDateFormatDateService().iso8601DateParse("2014-11-24T11:09:20.310023104Z"),
|
||||
"0d14967353dbbd2ee78abe209f026f71654da49692fa2b044296ec3c810027b3",
|
||||
"1.3.1",
|
||||
"amd64",
|
||||
"linux",
|
||||
0,
|
||||
808709069,
|
||||
null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.ImageSummary;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class ImagesParseTest extends BaseDockerParseTest<List<ImageSummary>> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/images.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public List<ImageSummary> expected() {
|
||||
return ImmutableList.of(
|
||||
ImageSummary.create("d7057cb020844f245031d27b76cb18af05db1cc3a96a29fa7777af75f5ac91a3",
|
||||
1442866547,
|
||||
"cfa753dfea5e68a24366dfba16e6edf573daa447abf65bc11619c1a98a3aff54",
|
||||
0,
|
||||
1095501,
|
||||
ImmutableList.of("docker.io/busybox:1.23.2", "docker.io/busybox:latest")),
|
||||
ImageSummary.create("633fcd11259e8d6bccfbb59a4086b95b0d0fb44edfc3912000ef1f70e8a7bfc6",
|
||||
1442598293,
|
||||
"b65c936b5fb601d680ed656b1ccf8ab857c0e5cb521043a005405c194e9a69f3",
|
||||
0,
|
||||
5607885,
|
||||
ImmutableList.of("docker.io/busybox:ubuntu-14.04", "jclouds:testTag")),
|
||||
ImageSummary.create("f4fddc471ec22fc1f7d37768132f1753bc171121e30ac2af7fcb0302588197c0",
|
||||
1442260874,
|
||||
"",
|
||||
5244426,
|
||||
5244426,
|
||||
ImmutableList.of("docker.io/alpine:3.2")),
|
||||
ImageSummary.create("91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c",
|
||||
1440102075,
|
||||
"d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
|
||||
0,
|
||||
188333286,
|
||||
ImmutableList.of("docker.io/ubuntu:14.04", "docker.io/ubuntu:latest"))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Info;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class Info2ParseTest extends BaseDockerParseTest<Info> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/info2.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Info expected() {
|
||||
return Info.create(
|
||||
0, // containers
|
||||
false, // debug
|
||||
"aufs", // driver
|
||||
ImmutableList.<List<String>>of(
|
||||
ImmutableList.of("Root Dir", "/var/lib/docker/aufs"),
|
||||
ImmutableList.of("Backing Filesystem", "extfs"),
|
||||
ImmutableList.of("Dirs", "117"),
|
||||
ImmutableList.of( "Dirperm1 Supported", "true")
|
||||
), // driverStatus
|
||||
"", // ExecutionDriver
|
||||
true, // IPv4Forwarding
|
||||
39, // Images
|
||||
"https://index.docker.io/v1/", // IndexServerAddress
|
||||
null, // InitPath
|
||||
null, // InitSha1
|
||||
"4.4.0-22-generic", // KernelVersion
|
||||
true, // MemoryLimit
|
||||
0, // NEventsListener
|
||||
33, // NFd
|
||||
83, // NGoroutines
|
||||
"Ubuntu 16.04 LTS", // OperatingSystem
|
||||
false, // SwapLimit
|
||||
"/var/lib/docker", // DockerRootDir
|
||||
null, // Labels
|
||||
8248356864L, // MemTotal
|
||||
4, // NCPU
|
||||
"KFWR:PMVY:BEWE:TD52:5WEU:NXF4:I6S3:WDIE:GCRD:L3YA:VWC4:ZRYZ", // ID
|
||||
"test" // name
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Info;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class InfoParseTest extends BaseDockerParseTest<Info> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/info.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Info expected() {
|
||||
return Info.create(
|
||||
0, // containers
|
||||
true, // debug
|
||||
"aufs", // driver
|
||||
ImmutableList.<List<String>>of(
|
||||
ImmutableList.of("Root Dir", "/mnt/sda1/var/lib/docker/aufs"),
|
||||
ImmutableList.of("Dirs", "46")
|
||||
), // driverStatus
|
||||
"native-0.2", // ExecutionDriver
|
||||
true, // IPv4Forwarding
|
||||
46, // Images
|
||||
"https://index.docker.io/v1/", // IndexServerAddress
|
||||
"/usr/local/bin/docker", // InitPath
|
||||
"", // InitSha1
|
||||
"3.16.7-tinycore64", // KernelVersion
|
||||
true, // MemoryLimit
|
||||
0, // NEventsListener
|
||||
10, // NFd
|
||||
11, // NGoroutines
|
||||
"Boot2Docker 1.4.1 (TCL 5.4); master : 86f7ec8 - Tue Dec 16 23:11:29 UTC 2014", // OperatingSystem
|
||||
true, // SwapLimit
|
||||
"/mnt/sda1/var/lib/docker", // DockerRootDir
|
||||
null, // Labels
|
||||
2105585664, // MemTotal
|
||||
8, // NCPU
|
||||
"7V5Y:IQ2M:HWIL:AZJV:HKRD:Q7OZ:3EQA:ZHMO:4LAD:OSIY:YBAA:BSX6", // ID
|
||||
"boot2docker" // name
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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.parse;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class NetworkParseTest extends BaseDockerParseTest<Network> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/network.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Network expected() {
|
||||
|
||||
Map<String, String> options = ImmutableMap.<String, String> builder()
|
||||
.put("com.docker.network.bridge.default_bridge", "true")
|
||||
.put("com.docker.network.bridge.enable_icc", "true")
|
||||
.put("com.docker.network.bridge.enable_ip_masquerade", "true")
|
||||
.put("com.docker.network.bridge.host_binding_ipv4", "0.0.0.0")
|
||||
.put("com.docker.network.bridge.name", "docker0")
|
||||
.put("com.docker.network.driver.mtu", "1500")
|
||||
.build();
|
||||
|
||||
return Network.create(
|
||||
"bridge", // Name
|
||||
"f2de39df4171b0dc801e8002d1d999b77256983dfc63041c0f34030aa3977566", // Id
|
||||
"local", // Scope
|
||||
"bridge", // Driver
|
||||
Network.IPAM.create(
|
||||
"default", // driver
|
||||
ImmutableList.of(Network.IPAM.Config.create("172.17.0.0/16", null, null)) // config
|
||||
),
|
||||
ImmutableMap.of("39b69226f9d79f5634485fb236a23b2fe4e96a0a94128390a7fbbcc167065867",
|
||||
Network.Details.create(
|
||||
"ed2419a97c1d9954d05b46e462e7002ea552f216e9b136b80a7db8d98b442eda", //endpointId
|
||||
"02:42:ac:11:00:02", // MAC
|
||||
"172.17.0.2/16", // ipv4address
|
||||
"" // ipv6address
|
||||
)
|
||||
),
|
||||
options);
|
||||
}
|
||||
}
|
|
@ -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.parse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Network;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class NetworksParseTest extends BaseDockerParseTest<List<Network>> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/networks.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public List<Network> expected() {
|
||||
return ImmutableList.of(
|
||||
|
||||
Network.create(
|
||||
"bridge", // Name
|
||||
"f2de39df4171b0dc801e8002d1d999b77256983dfc63041c0f34030aa3977566", // Id
|
||||
"local", // Scope
|
||||
"bridge", // Driver
|
||||
Network.IPAM.create(
|
||||
"default", // driver
|
||||
ImmutableList.of(Network.IPAM.Config.create("172.17.0.0/16", null, null)) // config
|
||||
),
|
||||
ImmutableMap.of("39b69226f9d79f5634485fb236a23b2fe4e96a0a94128390a7fbbcc167065867",
|
||||
Network.Details.create(
|
||||
"ed2419a97c1d9954d05b46e462e7002ea552f216e9b136b80a7db8d98b442eda", //endpointId
|
||||
"02:42:ac:11:00:02", // MAC
|
||||
"172.17.0.2/16", // ipv4address
|
||||
"" // ipv6address
|
||||
)
|
||||
),
|
||||
ImmutableMap.<String, String> builder()
|
||||
.put("com.docker.network.bridge.default_bridge", "true")
|
||||
.put("com.docker.network.bridge.enable_icc", "true")
|
||||
.put("com.docker.network.bridge.enable_ip_masquerade", "true")
|
||||
.put("com.docker.network.bridge.host_binding_ipv4", "0.0.0.0")
|
||||
.put("com.docker.network.bridge.name", "docker0")
|
||||
.put("com.docker.network.driver.mtu", "1500")
|
||||
.build()
|
||||
),
|
||||
Network.create(
|
||||
"none", // Name
|
||||
"e086a3893b05ab69242d3c44e49483a3bbbd3a26b46baa8f61ab797c1088d794", // Id
|
||||
"local", // Scope
|
||||
"null", // Driver
|
||||
Network.IPAM.create(
|
||||
"default", // driver
|
||||
ImmutableList.<Network.IPAM.Config>of() // config
|
||||
),
|
||||
ImmutableMap.<String, Network.Details> of(),
|
||||
ImmutableMap.<String, String> of()
|
||||
),
|
||||
Network.create(
|
||||
"host", // Name
|
||||
"13e871235c677f196c4e1ecebb9dc733b9b2d2ab589e30c539efeda84a24215e", // Id
|
||||
"local", // Scope
|
||||
"host", // Driver
|
||||
Network.IPAM.create(
|
||||
"default", // driver
|
||||
ImmutableList.<Network.IPAM.Config>of() // config
|
||||
),
|
||||
ImmutableMap.<String, Network.Details> of(),
|
||||
ImmutableMap.<String, String> of()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.parse;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Version;
|
||||
import org.jclouds.docker.internal.BaseDockerParseTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "unit")
|
||||
public class VersionParseTest extends BaseDockerParseTest<Version> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/version.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Version expected() {
|
||||
return Version.create(
|
||||
"1.15",
|
||||
"amd64",
|
||||
"c78088f",
|
||||
"go1.3.3",
|
||||
"3.16.4-tinycore64",
|
||||
"linux",
|
||||
"1.3.0");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# 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 kwart/alpine-ext:3.3-ssh
|
||||
MAINTAINER JClouds Dev <dev@jclouds.apache.org>
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# 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 scratch
|
|
@ -0,0 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDtTCCAp2gAwIBAgIJAL/TuOknjSR5MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTQxMjEyMTYwMDEyWhcNMjQxMjA5MTYwMDEyWjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAuUQcWlhrMXmzLSLiHUADdF98IHKRde7I1eDT91NndOtx4pKfvVc3WPei
|
||||
REIMksrU8F1r4A086h5++xxDf27LxR4EC9ry0Q6GgJ9Un9RB9clCWRhLw8awHAS7
|
||||
HgAEN8YOSCeF3qP+78muxyMkIKQbYn3TqqOzRZcK576hX+a6URNJDhbHHAzq2fxm
|
||||
rOSRVdPXzKLl48ABfmqJ6+KiXc6e7mQSgmwBLfh51zxmJNNwZ5e+6sfZ8oz4yM4y
|
||||
Kzek53GRSFj+VFNp5nS/x2072fUak2i6DGut5LibFfh1kqskIm+Iq5WwO15RbojZ
|
||||
CR6fkktCl5QOtea5p8SETZpwWfaddQIDAQABo4GnMIGkMB0GA1UdDgQWBBQtOc1g
|
||||
1gxisDQ7VTmRYI1U9WHVMDB1BgNVHSMEbjBsgBQtOc1g1gxisDQ7VTmRYI1U9WHV
|
||||
MKFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
|
||||
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAL/TuOknjSR5MAwGA1UdEwQF
|
||||
MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABxYn5JdJYC8FUITqymJeNZ72/a2GVf8
|
||||
+gGlWH+DuiyviEAGMGpv7O4GXfS/6UiUBO7zMe2z15fUvNgd5RQBh4T+l5bA9aS0
|
||||
5JhENIpEApiIcEII4ISIk6pTLmAZjWvqq2kStiiFPNvdKFclYqFuKHv847EA8kGz
|
||||
9u6MuUyFrJipWZ3g8zeYiwLWaAzvimbHomO7HU4pcvYaCSl7O5BQTToKwLfHcx5y
|
||||
UG6uRf+0auC5QbotiXpYNdXhIbSD/2xXbjxGwYy4yRWHINcbwfK8iVRhR4eSvtBC
|
||||
WvF3Vp8xLJxp6ujBd+a27AOWEiE1XM8oAoUpEzdIINY1GtUSbXzNboc=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"Hostname": "",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": true,
|
||||
"AttachStderr": true,
|
||||
"Tty": false,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Env": [
|
||||
"FOO=bar",
|
||||
"BAZ=quux"
|
||||
],
|
||||
"Cmd": [
|
||||
"date"
|
||||
],
|
||||
"Entrypoint": [""],
|
||||
"Image": "ubuntu",
|
||||
"Labels": {
|
||||
"com.example.vendor": "Acme",
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
"ExposedPorts": {
|
||||
"22/tcp": {}
|
||||
},
|
||||
"StopSignal": "SIGTERM",
|
||||
"HostConfig": {
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
"LxcConf": [{"lxc.utsname":"docker"}],
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"MemoryReservation": 0,
|
||||
"KernelMemory": 0,
|
||||
"CpuShares": 512,
|
||||
"CpuPeriod": 100000,
|
||||
"CpuQuota": 50000,
|
||||
"CpusetCpus": "0,1",
|
||||
"CpusetMems": "0,1",
|
||||
"BlkioWeight": 300,
|
||||
"MemorySwappiness": 60,
|
||||
"OomKillDisable": false,
|
||||
"PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
|
||||
"PublishAllPorts": false,
|
||||
"Privileged": false,
|
||||
"ReadonlyRootfs": false,
|
||||
"Dns": ["8.8.8.8"],
|
||||
"DnsOptions": [""],
|
||||
"DnsSearch": [""],
|
||||
"ExtraHosts": null,
|
||||
"VolumesFrom": ["parent", "other:ro"],
|
||||
"CapAdd": ["NET_ADMIN"],
|
||||
"CapDrop": ["MKNOD"],
|
||||
"GroupAdd": ["newgroup"],
|
||||
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
|
||||
"NetworkMode": "bridge",
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
{
|
||||
"AppArmorProfile": "",
|
||||
"Args": [
|
||||
"-c",
|
||||
"exit 9"
|
||||
],
|
||||
"Config": {
|
||||
"AttachStderr": true,
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": true,
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"exit 9"
|
||||
],
|
||||
"Domainname": "",
|
||||
"Entrypoint": null,
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"ExposedPorts": null,
|
||||
"Hostname": "ba033ac44011",
|
||||
"Image": "ubuntu",
|
||||
"Labels": {
|
||||
"com.example.vendor": "Acme",
|
||||
"com.example.license": "GPL",
|
||||
"com.example.version": "1.0"
|
||||
},
|
||||
"MacAddress": "",
|
||||
"NetworkDisabled": false,
|
||||
"OnBuild": null,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Tty": false,
|
||||
"User": "",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"StopSignal": "SIGTERM"
|
||||
},
|
||||
"Created": "2015-01-06T15:47:31.485331387Z",
|
||||
"Driver": "devicemapper",
|
||||
"ExecDriver": "native-0.2",
|
||||
"ExecIDs": null,
|
||||
"HostConfig": {
|
||||
"Binds": null,
|
||||
"BlkioWeight": 0,
|
||||
"CapAdd": null,
|
||||
"CapDrop": null,
|
||||
"ContainerIDFile": "",
|
||||
"CpusetCpus": "",
|
||||
"CpusetMems": "",
|
||||
"CpuShares": 0,
|
||||
"CpuPeriod": 100000,
|
||||
"Devices": [],
|
||||
"Dns": null,
|
||||
"DnsOptions": null,
|
||||
"DnsSearch": null,
|
||||
"ExtraHosts": null,
|
||||
"IpcMode": "",
|
||||
"Links": null,
|
||||
"LxcConf": [],
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"MemoryReservation": 0,
|
||||
"KernelMemory": 0,
|
||||
"OomKillDisable": false,
|
||||
"NetworkMode": "bridge",
|
||||
"PortBindings": {},
|
||||
"Privileged": false,
|
||||
"ReadonlyRootfs": false,
|
||||
"PublishAllPorts": false,
|
||||
"RestartPolicy": {
|
||||
"MaximumRetryCount": 2,
|
||||
"Name": "on-failure"
|
||||
},
|
||||
"LogConfig": {
|
||||
"Config": null,
|
||||
"Type": "json-file"
|
||||
},
|
||||
"SecurityOpt": null,
|
||||
"VolumesFrom": null,
|
||||
"Ulimits": [{}],
|
||||
"VolumeDriver": ""
|
||||
},
|
||||
"HostnamePath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hostname",
|
||||
"HostsPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/hosts",
|
||||
"LogPath": "/var/lib/docker/containers/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b/1eb5fabf5a03807136561b3c00adcd2992b535d624d5e18b6cdc6a6844d9767b-json.log",
|
||||
"Id": "ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39",
|
||||
"Image": "04c5d3b7b0656168630d3ba35d8889bd0e9caafcaeb3004d2bfbc47e7c5d35d2",
|
||||
"MountLabel": "",
|
||||
"Name": "/boring_euclid",
|
||||
"NetworkSettings": {
|
||||
"Bridge": "",
|
||||
"SandboxID": "",
|
||||
"HairpinMode": false,
|
||||
"LinkLocalIPv6Address": "",
|
||||
"LinkLocalIPv6PrefixLen": 0,
|
||||
"Ports": null,
|
||||
"SandboxKey": "",
|
||||
"SecondaryIPAddresses": null,
|
||||
"SecondaryIPv6Addresses": null,
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"MacAddress": "",
|
||||
"Networks": {
|
||||
"bridge": {
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"Path": "/bin/sh",
|
||||
"ProcessLabel": "",
|
||||
"ResolvConfPath": "/var/lib/docker/containers/ba033ac4401106a3b513bc9d639eee123ad78ca3616b921167cd74b20e25ed39/resolv.conf",
|
||||
"RestartCount": 1,
|
||||
"State": {
|
||||
"Error": "",
|
||||
"ExitCode": 9,
|
||||
"FinishedAt": "2015-01-06T15:47:32.080254511Z",
|
||||
"OOMKilled": false,
|
||||
"Paused": false,
|
||||
"Pid": 0,
|
||||
"Restarting": false,
|
||||
"Running": true,
|
||||
"StartedAt": "2015-01-06T15:47:32.072697474Z",
|
||||
"Status": "running"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Source": "/data",
|
||||
"Destination": "/data",
|
||||
"Mode": "ro,Z",
|
||||
"RW": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"Id":"c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2","Warnings":null}
|
|
@ -0,0 +1,159 @@
|
|||
{
|
||||
"Args": [
|
||||
"-iface",
|
||||
"ethwe",
|
||||
"-wait",
|
||||
"5",
|
||||
"-name",
|
||||
"7a:63:a2:39:7b:0f"
|
||||
],
|
||||
"Config": {
|
||||
"AttachStderr": false,
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"Cmd": [
|
||||
"-name",
|
||||
"7a:63:a2:39:7b:0f"
|
||||
],
|
||||
"CpuShares": 0,
|
||||
"Cpuset": "",
|
||||
"Domainname": "",
|
||||
"Entrypoint": [
|
||||
"/home/weave/weaver",
|
||||
"-iface",
|
||||
"ethwe",
|
||||
"-wait",
|
||||
"5"
|
||||
],
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"ExposedPorts": {
|
||||
"6783/tcp": {},
|
||||
"6783/udp": {}
|
||||
},
|
||||
"Hostname": "6c9932f478bd",
|
||||
"Image": "zettio/weave",
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"NetworkDisabled": false,
|
||||
"OnBuild": null,
|
||||
"OpenStdin": false,
|
||||
"PortSpecs": null,
|
||||
"SecurityOpts": null,
|
||||
"StdinOnce": false,
|
||||
"Tty": false,
|
||||
"User": "",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "/home/weave"
|
||||
},
|
||||
"Created": "2014-10-31T17:00:21.544197943Z",
|
||||
"Driver": "aufs",
|
||||
"ExecDriver": "native-0.2",
|
||||
"HostConfig": {
|
||||
"Binds": null,
|
||||
"CapAdd": ["NET_ADMIN"],
|
||||
"CapDrop": ["MKNOD"],
|
||||
"ContainerIDFile": "",
|
||||
"Devices": [],
|
||||
"Dns": [
|
||||
"8.8.8.8",
|
||||
"8.8.4.4"
|
||||
],
|
||||
"DnsSearch": null,
|
||||
"ExtraHosts": ["extra:169.254.0.1"],
|
||||
"Links": null,
|
||||
"LxcConf": [],
|
||||
"NetworkMode": "bridge",
|
||||
"PortBindings": {
|
||||
"6783/tcp": [
|
||||
{
|
||||
"HostIp": "",
|
||||
"HostPort": "6783"
|
||||
}
|
||||
],
|
||||
"6783/udp": [
|
||||
{
|
||||
"HostIp": "",
|
||||
"HostPort": "6783"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Privileged": true,
|
||||
"PublishAllPorts": false,
|
||||
"RestartPolicy": {
|
||||
"MaximumRetryCount": 0,
|
||||
"Name": ""
|
||||
},
|
||||
"VolumesFrom": null
|
||||
},
|
||||
"HostnamePath": "/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hostname",
|
||||
"HostsPath": "/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/hosts",
|
||||
"Id": "6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524",
|
||||
"Image": "57e570db16baba1e8c0d6f3c15868ddb400f64ff76ec948e65c3ca3f15fb3587",
|
||||
"MountLabel": "",
|
||||
"Name": "/weave",
|
||||
"NetworkSettings": {
|
||||
"Bridge": "",
|
||||
"SandboxID": "3ef128b055eb9ef62a6a2c281d97a2dfde5f47947d490f1dd2a81612611d961f",
|
||||
"HairpinMode": false,
|
||||
"LinkLocalIPv6Address": "",
|
||||
"LinkLocalIPv6PrefixLen": 0,
|
||||
"Ports": {},
|
||||
"SandboxKey": "/var/run/docker/netns/3ef128b055eb",
|
||||
"SecondaryIPAddresses": null,
|
||||
"SecondaryIPv6Addresses": null,
|
||||
"EndpointID": "9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6",
|
||||
"Gateway": "172.17.0.1",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"IPAddress": "172.17.0.2",
|
||||
"IPPrefixLen": 16,
|
||||
"IPv6Gateway": "",
|
||||
"MacAddress": "02:42:ac:11:00:02",
|
||||
"Networks": {
|
||||
"JCLOUDS_NETWORK": {
|
||||
"EndpointID": "04268fbb4dc368b5a53bb1c3f89294a4f0c72095deb944db3c4efc6d6a439304",
|
||||
"Gateway": "172.19.0.1",
|
||||
"IPAddress": "172.19.0.2",
|
||||
"IPPrefixLen": 16,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": "02:42:ac:13:00:02"
|
||||
},
|
||||
"bridge": {
|
||||
"EndpointID": "9e8dcc0c8288938a923018fee0728cee8e6de7c01a5150738ee6e51c1caf8cf6",
|
||||
"Gateway": "172.17.0.1",
|
||||
"IPAddress": "172.17.0.2",
|
||||
"IPPrefixLen": 16,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": "02:42:ac:11:00:02"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Node": {
|
||||
"IP": "10.10.10.10"
|
||||
},
|
||||
"Path": "/home/weave/weaver",
|
||||
"ProcessLabel": "",
|
||||
"ResolvConfPath": "/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/resolv.conf",
|
||||
"SecurityOpt": [],
|
||||
"State": {
|
||||
"Status": "running",
|
||||
"Running": true,
|
||||
"Paused": false,
|
||||
"Restarting": false,
|
||||
"OOMKilled": false,
|
||||
"Dead": false,
|
||||
"Pid": 10357,
|
||||
"ExitCode": 0,
|
||||
"Error": "",
|
||||
"StartedAt": "2015-11-10T09:33:21.68146124Z",
|
||||
"FinishedAt": "0001-01-01T00:00:00Z"
|
||||
},
|
||||
"Volumes": {},
|
||||
"VolumesRW": {}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue