mirror of https://github.com/apache/jclouds.git
JCLOUDS-737 update docker to support v1.3
This commit is contained in:
parent
b04fd71998
commit
6219b77dbc
|
@ -7,6 +7,10 @@ providers, it supports the same portable abstractions offered by jclouds.
|
|||
Please follow these steps to configure your workstation for jclouds-docker:
|
||||
|
||||
- install the latest Docker release (please visit https://docs.docker.com/installation/)
|
||||
If you are using boot2docker, notice that from version v1.3.0 the Docker daemon is set to use an encrypted TCP socket (--tls, or --tlsverify),
|
||||
then you need to create a p12 certificate using the following command:
|
||||
|
||||
`openssl pkcs12 -export -out $HOME/.jclouds/docker.p12 -inkey $HOME/.boot2docker/certs/boot2docker-vm/key.pem -in $HOME/.boot2docker/certs/boot2docker-vm/cert.pem -certfile $HOME/.boot2docker/certs/boot2docker-vm/ca.pem`
|
||||
|
||||
#How it works
|
||||
|
||||
|
@ -41,8 +45,8 @@ Please follow these steps to configure your workstation for jclouds-docker:
|
|||
As jclouds docker support is quite new, issues may occasionally arise. Please follow these steps to get things going again:
|
||||
|
||||
1. Remove all containers
|
||||
|
||||
`$ docker ps -a -q | xargs docker stop | xargs docker rm`
|
||||
|
||||
`$ docker ps -aq | xargs docker rm -f`
|
||||
2. remove all the images
|
||||
|
||||
`$ docker images -q | xargs docker rmi`
|
||||
`$ docker images -q | xargs docker rmi -f`
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<threadCount>1</threadCount>
|
||||
<systemPropertyVariables>
|
||||
<test.docker.endpoint>${test.docker.endpoint}</test.docker.endpoint>
|
||||
<test.docker.api-version>${test.docker.api-version}</test.docker.api-version>
|
||||
|
|
|
@ -16,22 +16,22 @@
|
|||
*/
|
||||
package org.jclouds.docker;
|
||||
|
||||
import org.jclouds.docker.features.RemoteApi;
|
||||
import org.jclouds.docker.features.ContainerApi;
|
||||
import org.jclouds.docker.features.ImageApi;
|
||||
import org.jclouds.docker.features.MiscApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Docker Remote API.
|
||||
*
|
||||
* @see <a href="https://docs.docker.com/reference/api/docker_remote_api/"></a>
|
||||
*/
|
||||
public interface DockerApi extends Closeable {
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Docker Remote API features.
|
||||
*/
|
||||
@Delegate
|
||||
RemoteApi getRemoteApi();
|
||||
MiscApi getMiscApi();
|
||||
|
||||
@Delegate
|
||||
ContainerApi getContainerApi();
|
||||
|
||||
@Delegate
|
||||
ImageApi getImageApi();
|
||||
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
|||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||
properties.setProperty(Constants.PROPERTY_CONNECTION_TIMEOUT, "1200000"); // 15 minutes
|
||||
properties.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
|
||||
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true,osVersionMatches=1[012].[01][04]");
|
||||
properties.setProperty(TEMPLATE, "osFamily=UBUNTU,os64Bit=true");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -66,16 +66,16 @@ public class DockerApiMetadata extends BaseHttpApiMetadata<DockerApi> {
|
|||
super(DockerApi.class);
|
||||
id("docker")
|
||||
.name("Docker API")
|
||||
.identityName("user")
|
||||
.credentialName("password")
|
||||
.identityName("Path to Certificate .p12 file")
|
||||
.credentialName("Password to Certificate")
|
||||
.documentation(URI.create("https://docs.docker.com/reference/api/docker_remote_api/"))
|
||||
.version("1.12")
|
||||
.defaultEndpoint("http://127.0.0.1:2375")
|
||||
.version("1.15")
|
||||
.defaultEndpoint("https://127.0.0.1:2376")
|
||||
.defaultProperties(DockerApiMetadata.defaultProperties())
|
||||
.view(typeToken(ComputeServiceContext.class))
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(
|
||||
DockerHttpApiModule.class,
|
||||
DockerParserModule.class,
|
||||
DockerHttpApiModule.class,
|
||||
DockerComputeServiceContextModule.class));
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,6 @@ public class ContainerToNodeMetadata implements Function<Container, NodeMetadata
|
|||
Image image = images.get().get(imageId);
|
||||
builder.operatingSystem(image.getOperatingSystem());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.jclouds.docker.compute.functions;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.ImageBuilder;
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
|
@ -44,6 +45,7 @@ public class ImageToImage implements Function<org.jclouds.docker.domain.Image, o
|
|||
@Override
|
||||
public Image apply(org.jclouds.docker.domain.Image from) {
|
||||
checkNotNull(from, "image");
|
||||
|
||||
String description = checkNotNull(Iterables.getFirst(from.repoTags(), "image must have at least one repo tag"));
|
||||
|
||||
OsFamily osFamily = osFamily().apply(description);
|
||||
|
|
|
@ -215,7 +215,7 @@ public class DockerTemplateOptions extends TemplateOptions implements Cloneable
|
|||
}
|
||||
|
||||
/**
|
||||
* @see DockerTemplateOptions#memory(int)
|
||||
* @see DockerTemplateOptions#memory
|
||||
*/
|
||||
public static DockerTemplateOptions memory(int memory) {
|
||||
DockerTemplateOptions options = new DockerTemplateOptions();
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.jclouds.docker.DockerApi;
|
|||
import org.jclouds.docker.compute.options.DockerTemplateOptions;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
|
@ -78,7 +79,7 @@ public class DockerComputeServiceAdapter implements
|
|||
|
||||
String imageId = checkNotNull(template.getImage().getId(), "template image id must not be null");
|
||||
String loginUser = template.getImage().getDefaultCredentials().getUser();
|
||||
String loginUserPassword = template.getImage().getDefaultCredentials().getPassword();
|
||||
String loginUserPassword = template.getImage().getDefaultCredentials().getOptionalPassword().or("password");
|
||||
|
||||
DockerTemplateOptions templateOptions = DockerTemplateOptions.class.cast(template.getOptions());
|
||||
int[] inboundPorts = templateOptions.getInboundPorts();
|
||||
|
@ -119,10 +120,15 @@ public class DockerComputeServiceAdapter implements
|
|||
}
|
||||
containerConfigBuilder.volumes(volumes);
|
||||
}
|
||||
|
||||
if (templateOptions.getEnv().isPresent()) {
|
||||
containerConfigBuilder.env(templateOptions.getEnv().get());
|
||||
}
|
||||
|
||||
Config containerConfig = containerConfigBuilder.build();
|
||||
|
||||
logger.debug(">> creating new container with containerConfig(%s)", containerConfig);
|
||||
Container container = api.getRemoteApi().createContainer(name, containerConfig);
|
||||
Container container = api.getContainerApi().createContainer(name, containerConfig);
|
||||
logger.trace("<< container(%s)", container.id());
|
||||
|
||||
HostConfig.Builder hostConfigBuilder = HostConfig.builder()
|
||||
|
@ -140,13 +146,13 @@ public class DockerComputeServiceAdapter implements
|
|||
}
|
||||
HostConfig hostConfig = hostConfigBuilder.build();
|
||||
|
||||
api.getRemoteApi().startContainer(container.id(), hostConfig);
|
||||
container = api.getRemoteApi().inspectContainer(container.id());
|
||||
api.getContainerApi().startContainer(container.id(), hostConfig);
|
||||
container = api.getContainerApi().inspectContainer(container.id());
|
||||
if (container.state().exitCode() != 0) {
|
||||
destroyNode(container.id());
|
||||
throw new IllegalStateException(String.format("Container %s has not started correctly", container.id()));
|
||||
}
|
||||
return new NodeAndInitialCredentials<Container>(container, container.id(),
|
||||
return new NodeAndInitialCredentials(container, container.id(),
|
||||
LoginCredentials.builder().user(loginUser).password(loginUserPassword).build());
|
||||
}
|
||||
|
||||
|
@ -156,21 +162,21 @@ public class DockerComputeServiceAdapter implements
|
|||
// todo they are only placeholders at the moment
|
||||
hardware.add(new HardwareBuilder().ids("micro").hypervisor("lxc").name("micro").processor(new Processor(1, 1)).ram(512).build());
|
||||
hardware.add(new HardwareBuilder().ids("small").hypervisor("lxc").name("small").processor(new Processor(1, 1)).ram(1024).build());
|
||||
hardware.add(new HardwareBuilder().ids("medium").hypervisor("lxc").name("medium").processor(new Processor(1, 1)).ram(2048).build());
|
||||
hardware.add(new HardwareBuilder().ids("large").hypervisor("lxc").name("large").processor(new Processor(1, 1)).ram(3072).build());
|
||||
hardware.add(new HardwareBuilder().ids("medium").hypervisor("lxc").name("medium").processor(new Processor(2, 1)).ram(2048).build());
|
||||
hardware.add(new HardwareBuilder().ids("large").hypervisor("lxc").name("large").processor(new Processor(2, 1)).ram(3072).build());
|
||||
return hardware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Image> listImages() {
|
||||
Set<Image> images = Sets.newHashSet();
|
||||
for (Image image : api.getRemoteApi().listImages()) {
|
||||
for (Image image : api.getImageApi().listImages()) {
|
||||
// less efficient than just listImages but returns richer json that needs repoTags coming from listImages
|
||||
Image inspected = api.getRemoteApi().inspectImage(image.id());
|
||||
Image inspected = api.getImageApi().inspectImage(image.id());
|
||||
if (inspected.repoTags().isEmpty()) {
|
||||
inspected = Image.create(inspected.id(), inspected.parent(), inspected.created(), inspected.container(),
|
||||
inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
|
||||
inspected.virtualSize(), image.repoTags());
|
||||
inspected = Image.create(inspected.id(), inspected.parent(), inspected.container(), inspected.created(),
|
||||
inspected.dockerVersion(), inspected.architecture(), inspected.os(), inspected.size(),
|
||||
inspected.virtualSize(), image.repoTags());
|
||||
}
|
||||
images.add(inspected);
|
||||
}
|
||||
|
@ -192,9 +198,9 @@ public class DockerComputeServiceAdapter implements
|
|||
@Override
|
||||
public Iterable<Container> listNodes() {
|
||||
Set<Container> containers = Sets.newHashSet();
|
||||
for (Container container : api.getRemoteApi().listContainers(ListContainerOptions.Builder.all(true))) {
|
||||
for (ContainerSummary containerSummary : api.getContainerApi().listContainers(ListContainerOptions.Builder.all(true))) {
|
||||
// less efficient than just listNodes but returns richer json
|
||||
containers.add(api.getRemoteApi().inspectContainer(container.id()));
|
||||
containers.add(api.getContainerApi().inspectContainer(containerSummary.id()));
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
@ -203,7 +209,7 @@ public class DockerComputeServiceAdapter implements
|
|||
public Iterable<Container> listNodesByIds(final Iterable<String> ids) {
|
||||
Set<Container> containers = Sets.newHashSet();
|
||||
for (String id : ids) {
|
||||
containers.add(api.getRemoteApi().inspectContainer(id));
|
||||
containers.add(api.getContainerApi().inspectContainer(id));
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
@ -215,18 +221,18 @@ public class DockerComputeServiceAdapter implements
|
|||
|
||||
@Override
|
||||
public Container getNode(String id) {
|
||||
return api.getRemoteApi().inspectContainer(id);
|
||||
return api.getContainerApi().inspectContainer(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNode(String id) {
|
||||
api.getRemoteApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
|
||||
api.getContainerApi().removeContainer(id, RemoveContainerOptions.Builder.force(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNode(String id) {
|
||||
api.getRemoteApi().stopContainer(id);
|
||||
api.getRemoteApi().startContainer(id);
|
||||
api.getContainerApi().stopContainer(id);
|
||||
api.getContainerApi().startContainer(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,8 +16,14 @@
|
|||
*/
|
||||
package org.jclouds.docker.config;
|
||||
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.handlers.DockerErrorHandler;
|
||||
import org.jclouds.docker.suppliers.KeyStoreSupplier;
|
||||
import org.jclouds.docker.suppliers.SSLContextWithKeysSupplier;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
|
@ -25,6 +31,9 @@ import org.jclouds.http.annotation.ServerError;
|
|||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
import org.jclouds.rest.config.HttpApiModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Configures the Docker connection.
|
||||
*/
|
||||
|
@ -37,4 +46,18 @@ public class DockerHttpApiModule extends HttpApiModule<DockerApi> {
|
|||
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DockerErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(DockerErrorHandler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This configures SSL certificate authentication when the Docker daemon is set to use an encrypted TCP socket
|
||||
*/
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(new TypeLiteral<Supplier<SSLContext>>() {
|
||||
}).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
|
||||
});
|
||||
bind(new TypeLiteral<Supplier<KeyStore>>() {
|
||||
}).to(new TypeLiteral<KeyStoreSupplier>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ public abstract class Config {
|
|||
private List<String> entrypoint = ImmutableList.of();
|
||||
private boolean networkDisabled;
|
||||
private List<String> onBuild = ImmutableList.of();
|
||||
private Map<String, String> restartPolicy = ImmutableMap.of();
|
||||
|
||||
public Builder hostname(String hostname) {
|
||||
this.hostname = hostname;
|
||||
|
@ -239,6 +240,11 @@ public abstract class Config {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder restartPolicy(Map<String, String> restartPolicy) {
|
||||
this.restartPolicy = ImmutableMap.copyOf(restartPolicy);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Config build() {
|
||||
return Config.create(hostname, domainname, user, memory, memorySwap, cpuShares, attachStdin, attachStdout,
|
||||
attachStderr, exposedPorts, tty, openStdin, stdinOnce, env, cmd, dns, image, volumes, volumesFrom,
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import static org.jclouds.docker.internal.NullSafeCopies.copyOf;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
// TODO it may be redundant (we already have Container value class)
|
||||
@AutoValue
|
||||
public abstract class ContainerSummary {
|
||||
|
||||
public abstract String id();
|
||||
|
||||
public abstract List<String> names();
|
||||
|
||||
public abstract String created();
|
||||
|
||||
public abstract String image();
|
||||
|
||||
public abstract String command();
|
||||
|
||||
public abstract List<Port> ports();
|
||||
|
||||
public abstract String status();
|
||||
|
||||
@SerializedNames({"Id", "Names", "Created", "Image", "Command", "Ports", "Status"})
|
||||
public static ContainerSummary create(String id, List<String> names, String created, String image, String command, List<Port> ports, String status) {
|
||||
return new AutoValue_ContainerSummary(id, copyOf(names), created, image, command, copyOf(ports), status);
|
||||
}
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ public abstract class HostConfig {
|
|||
|
||||
public abstract List<String> binds();
|
||||
|
||||
public abstract Map<String, String> lxcConf();
|
||||
public abstract List<Map<String, String>> lxcConf();
|
||||
|
||||
public abstract boolean privileged();
|
||||
|
||||
|
@ -53,7 +53,7 @@ public abstract class HostConfig {
|
|||
|
||||
@SerializedNames({ "ContainerIDFile", "Binds", "LxcConf", "Privileged", "Dns", "DnsSearch", "PortBindings",
|
||||
"Links", "PublishAllPorts", "VolumesFrom" })
|
||||
public static HostConfig create(String containerIDFile, List<String> binds, Map<String, String> lxcConf,
|
||||
public static HostConfig create(String containerIDFile, List<String> binds, List<Map<String, String>> lxcConf,
|
||||
boolean privileged, String dns, String dnsSearch, Map<String, List<Map<String, String>>> portBindings,
|
||||
List<String> links, boolean publishAllPorts, List<String> volumesFrom) {
|
||||
return new AutoValue_HostConfig(containerIDFile, copyOf(binds), copyOf(lxcConf), privileged, dns, dnsSearch,
|
||||
|
@ -72,7 +72,7 @@ public abstract class HostConfig {
|
|||
|
||||
private String containerIDFile;
|
||||
private List<String> binds = Lists.newArrayList();
|
||||
private Map<String, String> lxcConf = Maps.newLinkedHashMap();
|
||||
private List<Map<String, String>> lxcConf = Lists.newArrayList();
|
||||
private boolean privileged;
|
||||
private String dns;
|
||||
private String dnsSearch;
|
||||
|
@ -91,8 +91,8 @@ public abstract class HostConfig {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder lxcConf(Map<String, String> lxcConf) {
|
||||
this.lxcConf.putAll(checkNotNull(lxcConf, "lxcConf"));
|
||||
public Builder lxcConf(List<Map<String, String>> lxcConf) {
|
||||
this.lxcConf.addAll(checkNotNull(lxcConf, "lxcConf"));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,10 +48,11 @@ public abstract class Image {
|
|||
public abstract List<String> repoTags();
|
||||
|
||||
@SerializedNames({ "Id", "Parent", "Created", "Container", "DockerVersion", "Architecture", "Os", "Size",
|
||||
"VirtualSize", "RepoTags", "Architecture" })
|
||||
"VirtualSize", "RepoTags" })
|
||||
public static Image create(String id, String parent, String created, String container, String dockerVersion,
|
||||
String architecture, String os, long size, long virtualSize, List<String> repoTags) {
|
||||
return new AutoValue_Image(id, parent, created, container, dockerVersion, architecture, os, size, virtualSize,
|
||||
copyOf(repoTags));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.domain;
|
||||
|
||||
import org.jclouds.json.SerializedNames;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
@AutoValue
|
||||
public abstract class Info {
|
||||
|
||||
public abstract int containers();
|
||||
|
||||
public abstract int images();
|
||||
|
||||
public abstract String driver();
|
||||
|
||||
public abstract String executionDriver();
|
||||
|
||||
public abstract String kernelVersion();
|
||||
|
||||
public abstract int debug();
|
||||
|
||||
public abstract int nFd();
|
||||
|
||||
public abstract int nGoroutines();
|
||||
|
||||
public abstract int nEventsListener();
|
||||
|
||||
public abstract String initPath();
|
||||
|
||||
public abstract String indexServerAddress();
|
||||
|
||||
public abstract int memoryLimit();
|
||||
|
||||
public abstract int swapLimit();
|
||||
|
||||
public abstract int iPv4Forwarding();
|
||||
|
||||
@SerializedNames(
|
||||
{"Containers", "Images", "Driver", "ExecutionDriver", "KernelVersion", "Debug", "NFd", "NGoroutines",
|
||||
"NEventsListener", "InitPath", "IndexServerAddress", "MemoryLimit", "SwapLimit", "IPv4Forwarding"})
|
||||
public static Info create(int containers, int images, String driver, String executionDriver, String kernelVersion, int debug,
|
||||
int nFd, int nGoroutines, int nEventsListener, String initPath, String indexServerAddress,
|
||||
int memoryLimit, int swapLimit, int iPv4Forwarding) {
|
||||
return new AutoValue_Info(containers, images, driver, executionDriver, kernelVersion, debug, nFd, nGoroutines,
|
||||
nEventsListener, initPath, indexServerAddress, memoryLimit, swapLimit, iPv4Forwarding);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,9 @@ import com.google.auto.value.AutoValue;
|
|||
|
||||
@AutoValue
|
||||
public abstract class Version {
|
||||
|
||||
public abstract String apiVersion();
|
||||
|
||||
public abstract String arch();
|
||||
|
||||
public abstract String gitCommit();
|
||||
|
@ -34,9 +37,9 @@ public abstract class Version {
|
|||
|
||||
public abstract String version();
|
||||
|
||||
@SerializedNames({ "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
|
||||
public static Version create(String arch, String gitCommit, String goVersion, String kernelVersion, String os,
|
||||
String version) {
|
||||
return new AutoValue_Version(arch, gitCommit, goVersion, kernelVersion, os, version);
|
||||
@SerializedNames({ "ApiVersion", "Arch", "GitCommit", "GoVersion", "KernelVersion", "Os", "Version" })
|
||||
public static Version create(String apiVersion, String arch, String gitCommit, String goVersion,
|
||||
String kernelVersion, String os, String version) {
|
||||
return new AutoValue_Version(apiVersion, arch, gitCommit, goVersion, kernelVersion, os, version);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -33,34 +31,18 @@ import javax.ws.rs.core.MediaType;
|
|||
import org.jclouds.Fallbacks;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.HostConfig;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.domain.Version;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.docker.options.CommitOptions;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.docker.options.ListImageOptions;
|
||||
import org.jclouds.docker.options.RemoveContainerOptions;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface RemoteApi extends Closeable {
|
||||
|
||||
/**
|
||||
* Get the information of the current docker version.
|
||||
*
|
||||
* @return The information of the current docker version.
|
||||
*/
|
||||
@Named("version")
|
||||
@GET
|
||||
@Path("/version")
|
||||
Version getVersion();
|
||||
public interface ContainerApi {
|
||||
|
||||
/**
|
||||
* List all running containers
|
||||
|
@ -70,8 +52,8 @@ public interface RemoteApi extends Closeable {
|
|||
@Named("containers:list")
|
||||
@GET
|
||||
@Path("/containers/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Container> listContainers();
|
||||
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
|
||||
List<ContainerSummary> listContainers();
|
||||
|
||||
/**
|
||||
* List all running containers
|
||||
|
@ -82,8 +64,8 @@ public interface RemoteApi extends Closeable {
|
|||
@Named("containers:list")
|
||||
@GET
|
||||
@Path("/containers/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Container> listContainers(ListContainerOptions options);
|
||||
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
|
||||
List<ContainerSummary> listContainers(ListContainerOptions options);
|
||||
|
||||
/**
|
||||
* Create a container
|
||||
|
@ -172,85 +154,4 @@ public interface RemoteApi extends Closeable {
|
|||
@Path("/commit")
|
||||
Image commit(CommitOptions options);
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Image> listImages();
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @param options the configuration to list images (@see ListImageOptions)
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
|
||||
Set<Image> listImages(ListImageOptions options);
|
||||
|
||||
/**
|
||||
* Inspect an image
|
||||
*
|
||||
* @param imageName The id of the image to inspect.
|
||||
* @return low-level information on the image name
|
||||
*/
|
||||
@Named("image:inspect")
|
||||
@GET
|
||||
@Path("/images/{name}/json")
|
||||
Image inspectImage(@PathParam("name") String imageName);
|
||||
|
||||
/**
|
||||
* Create an image, either by pull it from the registry or by importing it
|
||||
*
|
||||
* @param options the configuration to create an image (@see CreateImageOptions)
|
||||
* @return a stream of the image creation.
|
||||
*/
|
||||
@Named("image:create")
|
||||
@POST
|
||||
@Path("/images/create")
|
||||
InputStream createImage(CreateImageOptions options);
|
||||
|
||||
/**
|
||||
* Delete an image.
|
||||
*
|
||||
* @param name the image name to be deleted
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name);
|
||||
|
||||
/**
|
||||
* Remove the image from the filesystem by name
|
||||
*
|
||||
* @param name the name of the image to be removed
|
||||
* @param options the image deletion's options (@see DeleteImageOptions)
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name, DeleteImageOptions options);
|
||||
|
||||
/**
|
||||
* Build an image from Dockerfile via stdin
|
||||
*
|
||||
* @param inputStream The stream must be a tar archive compressed with one of the following algorithms: identity
|
||||
* (no compression), gzip, bzip2, xz.
|
||||
* @param options the image build's options (@see BuildOptions)
|
||||
* @return a stream of the build execution
|
||||
*/
|
||||
@Named("image:build")
|
||||
@POST
|
||||
@Path("/build")
|
||||
@Headers(keys = "Content-Type", values = "application/tar")
|
||||
InputStream build(Payload inputStream, BuildOptions options);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Fallbacks;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.docker.options.ListImageOptions;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface ImageApi {
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
|
||||
List<Image> listImages();
|
||||
|
||||
/**
|
||||
* List images
|
||||
*
|
||||
* @param options the configuration to list images (@see ListImageOptions)
|
||||
* @return the images available.
|
||||
*/
|
||||
@Named("images:list")
|
||||
@GET
|
||||
@Path("/images/json")
|
||||
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
|
||||
List<Image> listImages(ListImageOptions options);
|
||||
|
||||
/**
|
||||
* Inspect an image
|
||||
*
|
||||
* @param imageName The id of the image to inspect.
|
||||
* @return low-level information on the image name
|
||||
*/
|
||||
@Named("image:inspect")
|
||||
@GET
|
||||
@Path("/images/{name}/json")
|
||||
@Fallback(Fallbacks.VoidOnNotFoundOr404.class)
|
||||
Image inspectImage(@PathParam("name") String imageName);
|
||||
|
||||
/**
|
||||
* Create an image, either by pull it from the registry or by importing it
|
||||
*
|
||||
* @param options the configuration to create an image (@see CreateImageOptions)
|
||||
* @return a stream of the image creation.
|
||||
*/
|
||||
@Named("image:create")
|
||||
@POST
|
||||
@Path("/images/create")
|
||||
InputStream createImage(CreateImageOptions options);
|
||||
|
||||
/**
|
||||
* Delete an image.
|
||||
*
|
||||
* @param name the image name to be deleted
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name);
|
||||
|
||||
/**
|
||||
* Remove the image from the filesystem by name
|
||||
*
|
||||
* @param name the name of the image to be removed
|
||||
* @param options the image deletion's options (@see DeleteImageOptions)
|
||||
* @return the stream of the deletion execution.
|
||||
*/
|
||||
@Named("image:delete")
|
||||
@DELETE
|
||||
@Path("/images/{name}")
|
||||
InputStream deleteImage(@PathParam("name") String name, DeleteImageOptions options);
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.docker.domain.Info;
|
||||
import org.jclouds.docker.domain.Version;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.rest.annotations.Headers;
|
||||
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public interface MiscApi {
|
||||
|
||||
/**
|
||||
* Get the information of the current docker version.
|
||||
*
|
||||
* @return The information of the current docker version.
|
||||
*/
|
||||
@Named("version")
|
||||
@GET
|
||||
@Path("/version")
|
||||
Version getVersion();
|
||||
|
||||
/**
|
||||
* Get the information of the current docker version.
|
||||
*
|
||||
* @return The information of the current docker version.
|
||||
*/
|
||||
@Named("info")
|
||||
@GET
|
||||
@Path("/info")
|
||||
Info getInfo();
|
||||
|
||||
|
||||
/**
|
||||
* Build an image from Dockerfile via stdin
|
||||
*
|
||||
* @param inputStream The stream must be a tar archive compressed with one of the following algorithms: identity
|
||||
* (no compression), gzip, bzip2, xz.
|
||||
* @param options the image build's options (@see BuildOptions)
|
||||
* @return a stream of the build execution
|
||||
*/
|
||||
@Named("image:build")
|
||||
@POST
|
||||
@Path("/build")
|
||||
@Headers(keys = "Content-Type", values = "application/tar")
|
||||
InputStream build(Payload inputStream, BuildOptions options);
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.crypto.Pems;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
@Singleton
|
||||
public class KeyStoreSupplier implements Supplier<KeyStore> {
|
||||
private final Crypto crypto;
|
||||
private final Supplier<Credentials> creds;
|
||||
|
||||
@Inject
|
||||
KeyStoreSupplier(Crypto crypto, @Provider Supplier<Credentials> creds) {
|
||||
this.crypto = crypto;
|
||||
this.creds = creds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyStore get() {
|
||||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
String cert = checkNotNull(currentCreds.identity, "credential supplier returned null identity (should be cert)");
|
||||
String keyStorePassword = checkNotNull(currentCreds.credential,
|
||||
"credential supplier returned null credential (should be keyStorePassword)");
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
|
||||
File certFile = new File(checkNotNull(cert));
|
||||
if (certFile.isFile()) { // cert is path to pkcs12 file
|
||||
FileInputStream stream = new FileInputStream(certFile);
|
||||
try {
|
||||
keyStore.load(stream, keyStorePassword.toCharArray());
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
} else { // cert is PEM encoded, containing private key and certs
|
||||
|
||||
// split in private key and certs
|
||||
int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
|
||||
int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
|
||||
if (privateKeyBeginIdx != -1) {
|
||||
String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
|
||||
|
||||
StringBuilder pemCerts = new StringBuilder();
|
||||
int certsBeginIdx = 0;
|
||||
|
||||
do {
|
||||
certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
|
||||
|
||||
if (certsBeginIdx >= 0) {
|
||||
int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
|
||||
pemCerts.append(cert.substring(certsBeginIdx, certsEndIdx));
|
||||
certsBeginIdx = certsEndIdx;
|
||||
}
|
||||
} while (certsBeginIdx != -1);
|
||||
|
||||
// parse private key
|
||||
KeySpec keySpec = Pems.privateKeySpec(ByteSource.wrap(pemPrivateKey.getBytes(Charsets.UTF_8)));
|
||||
PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
|
||||
|
||||
// populate keystore with private key and certs
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
|
||||
pemCerts.toString().getBytes(Charsets.UTF_8)));
|
||||
keyStore.load(null);
|
||||
keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
|
||||
certs.toArray(new Certificate[0]));
|
||||
} else {
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
}
|
||||
return keyStore;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw propagate(e);
|
||||
} catch (KeyStoreException e) {
|
||||
throw propagate(e);
|
||||
} catch (CertificateException e) {
|
||||
throw propagate(e);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw propagate(e);
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.docker.suppliers;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.config.SSLModule.TrustAllCerts;
|
||||
import org.jclouds.location.Provider;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
@Singleton
|
||||
public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
|
||||
private final Supplier<KeyStore> keyStore;
|
||||
private final TrustManager[] trustManager;
|
||||
private final Supplier<Credentials> creds;
|
||||
|
||||
@Inject
|
||||
SSLContextWithKeysSupplier(Supplier<KeyStore> keyStore, @Provider Supplier<Credentials> creds, HttpUtils utils,
|
||||
TrustAllCerts trustAllCerts) {
|
||||
this.keyStore = keyStore;
|
||||
this.trustManager = utils.trustAllCerts() ? new TrustManager[] { trustAllCerts } : null;
|
||||
this.creds = creds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext get() {
|
||||
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
|
||||
String keyStorePassword = checkNotNull(currentCreds.credential,
|
||||
"credential supplier returned null credential (should be keyStorePassword)");
|
||||
KeyManagerFactory kmf;
|
||||
try {
|
||||
kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
kmf.init(keyStore.get(), keyStorePassword.toCharArray());
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
|
||||
return sc;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw propagate(e);
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
throw propagate(e);
|
||||
} catch (KeyStoreException e) {
|
||||
throw propagate(e);
|
||||
} catch (KeyManagementException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
|
|||
import org.jboss.shrinkwrap.api.exporter.TarExporter;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.apis.BaseApiLiveTest;
|
||||
import org.jclouds.compute.config.ComputeServiceProperties;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
|
@ -58,6 +59,7 @@ public class BaseDockerApiLiveTest extends BaseApiLiveTest<DockerApi> {
|
|||
Properties overrides = super.setupProperties();
|
||||
overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "15");
|
||||
overrides.setProperty("jclouds.ssh.retry-auth", "true");
|
||||
overrides.setProperty(ComputeServiceProperties.IMAGE_LOGIN_USER, "root:password");
|
||||
return overrides;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,17 +22,24 @@ import static org.testng.Assert.assertNotNull;
|
|||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.compute.options.DockerTemplateOptions;
|
||||
import org.jclouds.docker.compute.strategy.DockerComputeServiceAdapter;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.annotations.AfterGroups;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Injector;
|
||||
|
@ -41,27 +48,47 @@ import com.google.inject.Module;
|
|||
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceAdapterLiveTest")
|
||||
public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String SSHABLE_IMAGE = "tutum/ubuntu";
|
||||
private static final String SSHABLE_IMAGE_TAG = "trusty";
|
||||
private Image defaultImage;
|
||||
|
||||
private DockerComputeServiceAdapter adapter;
|
||||
private TemplateBuilder templateBuilder;
|
||||
private ComputeService computeService;
|
||||
private NodeAndInitialCredentials<Container> guest;
|
||||
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
super.initialize();
|
||||
String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
|
||||
Image image = api.getImageApi().inspectImage(imageName);
|
||||
if (image == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
|
||||
api.getImageApi().createImage(options);
|
||||
}
|
||||
defaultImage = api.getImageApi().inspectImage(imageName);
|
||||
assertNotNull(defaultImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DockerApi create(Properties props, Iterable<Module> modules) {
|
||||
Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
|
||||
adapter = injector.getInstance(DockerComputeServiceAdapter.class);
|
||||
templateBuilder = injector.getInstance(TemplateBuilder.class);
|
||||
computeService = injector.getInstance(ComputeService.class);
|
||||
return injector.getInstance(DockerApi.class);
|
||||
}
|
||||
|
||||
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
|
||||
String group = "foo";
|
||||
String name = "container-" + new Random().nextInt();
|
||||
String name = "container" + new Random().nextInt();
|
||||
|
||||
Template template = templateBuilder.smallest()
|
||||
.osDescriptionMatches("jclouds/default:latest").build();
|
||||
Template template = templateBuilder.imageId(defaultImage.id()).build();
|
||||
|
||||
DockerTemplateOptions options = template.getOptions().as(DockerTemplateOptions.class);
|
||||
options.env(ImmutableList.of("ROOT_PASS=password"));
|
||||
guest = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
|
||||
assertEquals(guest.getNodeId(), guest.getNode().id() + "");
|
||||
assertEquals(guest.getNodeId(), guest.getNode().id());
|
||||
}
|
||||
|
||||
public void testListHardwareProfiles() {
|
||||
|
@ -78,6 +105,9 @@ public class DockerComputeServiceAdapterLiveTest extends BaseDockerApiLiveTest {
|
|||
if (guest != null) {
|
||||
adapter.destroyNode(guest.getNode().id() + "");
|
||||
}
|
||||
if (defaultImage != null) {
|
||||
api.getImageApi().deleteImage(defaultImage.id(), DeleteImageOptions.Builder.force(true));
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,30 +16,67 @@
|
|||
*/
|
||||
package org.jclouds.docker.compute;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static java.util.logging.Logger.getAnonymousLogger;
|
||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.runAsRoot;
|
||||
import static org.jclouds.util.Predicates2.retry;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.JettyStatements;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.domain.ExecResponse;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.compute.util.OpenSocketFinder;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.compute.options.DockerTemplateOptions;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.features.ImageApi;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.predicates.SocketOpen;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Live tests for the {@link org.jclouds.compute.ComputeService} integration.
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "DockerComputeServiceLiveTest")
|
||||
public class DockerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||
public class DockerComputeServiceLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
|
||||
private static final String DEFAULT_JCLOUDS_IMAGE = "jclouds/default";
|
||||
private static final String SSHABLE_IMAGE = "tutum/ubuntu";
|
||||
private static final String SSHABLE_IMAGE_TAG = "trusty";
|
||||
private Image defaultImage;
|
||||
protected Template template;
|
||||
protected Predicate<HostAndPort> socketTester;
|
||||
protected OpenSocketFinder openSocketFinder;
|
||||
|
||||
protected ComputeService client;
|
||||
|
||||
public DockerComputeServiceLiveTest() {
|
||||
provider = "docker";
|
||||
|
@ -50,93 +87,134 @@ public class DockerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
return new SshjSshClientModule();
|
||||
}
|
||||
|
||||
@BeforeGroups(groups = { "integration", "live" })
|
||||
@Override
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
buildSocketTester();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeContext() {
|
||||
super.initializeContext();
|
||||
Optional<? extends Image> optionalImage = Iterables.tryFind(client.listImages(), new Predicate<Image>() {
|
||||
@Override
|
||||
public boolean apply(Image image) {
|
||||
return image.getName().equals(DEFAULT_JCLOUDS_IMAGE);
|
||||
}
|
||||
});
|
||||
if (optionalImage.isPresent()) {
|
||||
defaultImage = optionalImage.get();
|
||||
} else {
|
||||
Assert.fail("Please create an ssh-able image called " + DEFAULT_JCLOUDS_IMAGE);
|
||||
client = view.getComputeService();
|
||||
|
||||
String imageName = SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG;
|
||||
org.jclouds.docker.domain.Image image = imageApi().inspectImage(imageName);
|
||||
if (image == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(SSHABLE_IMAGE).tag(SSHABLE_IMAGE_TAG);
|
||||
imageApi().createImage(options);
|
||||
}
|
||||
image = imageApi().inspectImage(imageName);
|
||||
defaultImage = client.getImage(image.id());
|
||||
assertNotNull(defaultImage);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@Override
|
||||
protected void tearDownContext() {
|
||||
super.tearDownContext();
|
||||
if (defaultImage != null) {
|
||||
imageApi().deleteImage(SSHABLE_IMAGE + ":" + SSHABLE_IMAGE_TAG, DeleteImageOptions.Builder.force(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
private ImageApi imageApi() {
|
||||
return client.getContext().unwrapApi(DockerApi.class).getImageApi();
|
||||
}
|
||||
|
||||
protected Template buildTemplate(TemplateBuilder templateBuilder) {
|
||||
return templateBuilder.imageId(defaultImage.getId()).build();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testOptionToNotBlock() throws Exception {
|
||||
// Docker ComputeService implementation has to block until the node
|
||||
// is provisioned, to be able to return it.
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
|
||||
// Docker does not support tags
|
||||
protected void trackProcessOnNode(Statement process, String processName, NodeMetadata node) {
|
||||
ServiceStats stats = new ServiceStats();
|
||||
Stopwatch watch = Stopwatch.createStarted();
|
||||
ExecResponse exec = client.runScriptOnNode(node.getId(), process, runAsRoot(false).wrapInInitScript(false));
|
||||
stats.backgroundProcessMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
|
||||
|
||||
Container container = client.getContext().unwrapApi(DockerApi.class).getContainerApi().inspectContainer(node.getId());
|
||||
Map<String, List<Map<String, String>>> ports = container.networkSettings().ports();
|
||||
int port = Integer.parseInt(getOnlyElement(ports.get("8080/tcp")).get("HostPort"));
|
||||
|
||||
watch.reset().start();
|
||||
HostAndPort socket;
|
||||
try {
|
||||
socket = openSocketFinder.findOpenSocketOnNode(node, port, 600, TimeUnit.SECONDS);
|
||||
} catch (NoSuchElementException e) {
|
||||
throw new NoSuchElementException(format("%s%n%s%s", e.getMessage(), exec.getOutput(), exec.getError()));
|
||||
}
|
||||
stats.socketOpenMilliseconds = watch.elapsed(TimeUnit.MILLISECONDS);
|
||||
getAnonymousLogger().info(format("<< %s on node(%s)[%s] %s", processName, node.getId(), socket, stats));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
|
||||
// Docker does not support user metadata
|
||||
static class ServiceStats {
|
||||
long backgroundProcessMilliseconds;
|
||||
long socketOpenMilliseconds;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return format("[backgroundProcessMilliseconds=%s, socketOpenMilliseconds=%s]",
|
||||
backgroundProcessMilliseconds, socketOpenMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testCreateAndRunAService() throws Exception {
|
||||
// Docker does not support blockOnPort
|
||||
protected String exec(final String nodeId, String command) {
|
||||
return exec(nodeId, Statements.exec(command));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = { "testCompareSizes" })
|
||||
public void testAScriptExecutionAfterBootWithBasicTemplate() throws Exception {
|
||||
super.testAScriptExecutionAfterBootWithBasicTemplate();
|
||||
protected String exec(final String nodeId, Statement command) {
|
||||
return client.runScriptOnNode(nodeId, command, runAsRoot(false).wrapInInitScript(false)).getOutput().trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class)
|
||||
public void testSuspendResume() throws Exception {
|
||||
super.testSuspendResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testGetNodesWithDetails() throws Exception {
|
||||
super.testGetNodesWithDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testListNodes() throws Exception {
|
||||
super.testListNodes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testListNodesByIds() throws Exception {
|
||||
super.testListNodesByIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
|
||||
public void testDestroyNodes() {
|
||||
super.testDestroyNodes();
|
||||
}
|
||||
|
||||
@Test(enabled = true, expectedExceptions = NullPointerException.class)
|
||||
public void testCorrectExceptionRunningNodesNotFound() throws Exception {
|
||||
super.testCorrectExceptionRunningNodesNotFound();
|
||||
}
|
||||
|
||||
@Test(enabled = true, expectedExceptions = NullPointerException.class)
|
||||
public void testCorrectAuthException() throws Exception {
|
||||
// Docker does not support authentication yet
|
||||
super.testCorrectAuthException();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.jclouds.docker.domain.State;
|
|||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationBuilder;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -59,6 +60,9 @@ import com.google.inject.Guice;
|
|||
*/
|
||||
@Test(groups = "unit", testName = "ContainerToNodeMetadataTest")
|
||||
public class ContainerToNodeMetadataTest {
|
||||
|
||||
private LoginCredentials credentials;
|
||||
|
||||
private ContainerToNodeMetadata function;
|
||||
|
||||
private Container container;
|
||||
|
@ -164,6 +168,8 @@ public class ContainerToNodeMetadataTest {
|
|||
}
|
||||
};
|
||||
|
||||
credentials = LoginCredentials.builder().user("foo").password("bar").build();
|
||||
|
||||
function = new ContainerToNodeMetadata(providerMetadata, toPortableStatus(), namingConvention, images, locations);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableList;
|
|||
*/
|
||||
@Test(groups = "unit", testName = "ImageToImageTest")
|
||||
public class ImageToImageTest {
|
||||
|
||||
private ImageToImage function;
|
||||
|
||||
private org.jclouds.docker.domain.Image image;
|
||||
|
|
|
@ -16,55 +16,52 @@
|
|||
*/
|
||||
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.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.domain.Image;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.DeleteImageOptions;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "live", testName = "RemoteApiLiveTest", singleThreaded = true)
|
||||
public class RemoteApiLiveTest extends BaseDockerApiLiveTest {
|
||||
public class ContainerApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String BUSYBOX_IMAGE = "busybox";
|
||||
private Container container = null;
|
||||
private Image image = null;
|
||||
protected static final String BUSYBOX_IMAGE_TAG = "busybox:ubuntu-12.04";
|
||||
protected Image image = null;
|
||||
|
||||
@Test
|
||||
public void testVersion() {
|
||||
assertEquals(api().getVersion().version(), "1.0.0");
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testVersion")
|
||||
public void testCreateImage() throws IOException, InterruptedException {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(BUSYBOX_IMAGE);
|
||||
consumeStream(api().createImage(options));
|
||||
image = api().inspectImage(BUSYBOX_IMAGE);
|
||||
@BeforeClass
|
||||
protected void init() {
|
||||
if (api.getImageApi().inspectImage(BUSYBOX_IMAGE_TAG) == null) {
|
||||
CreateImageOptions options = CreateImageOptions.Builder.fromImage(BUSYBOX_IMAGE_TAG);
|
||||
InputStream createImageStream = api.getImageApi().createImage(options);
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
image = api.getImageApi().inspectImage(BUSYBOX_IMAGE_TAG);
|
||||
assertNotNull(image);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateImage")
|
||||
public void testListImages() {
|
||||
assertNotNull(api().listImages());
|
||||
@AfterClass
|
||||
protected void tearDown() {
|
||||
if (image != null) {
|
||||
api.getImageApi().deleteImage(BUSYBOX_IMAGE_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListImages")
|
||||
public void testCreateContainer() throws IOException, InterruptedException {
|
||||
Config containerConfig = Config.builder().image(image.id())
|
||||
.cmd(ImmutableList.of("/bin/sh", "-c", "while true; do echo hello world; sleep 1; done"))
|
||||
|
@ -86,30 +83,23 @@ public class RemoteApiLiveTest extends BaseDockerApiLiveTest {
|
|||
assertFalse(api().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListContainers() {
|
||||
List<ContainerSummary> containerSummaries = api().listContainers(ListContainerOptions.Builder.all(true));
|
||||
for (ContainerSummary containerSummary : containerSummaries) {
|
||||
assertNotNull(containerSummary.id());
|
||||
assertNotNull(containerSummary.image());
|
||||
assertFalse(containerSummary.names().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testStopContainer", expectedExceptions = NullPointerException.class)
|
||||
public void testRemoveContainer() {
|
||||
api().removeContainer(container.id());
|
||||
assertFalse(api().inspectContainer(container.id()).state().running());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testRemoveContainer", expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testDeleteImage() {
|
||||
consumeStream(api().deleteImage(image.id()));
|
||||
assertNull(api().inspectImage(image.id()));
|
||||
}
|
||||
|
||||
public void testBuildImage() throws IOException, InterruptedException, URISyntaxException {
|
||||
BuildOptions options = BuildOptions.Builder.tag("testBuildImage").verbose(false).nocache(false);
|
||||
String buildStream = consumeStream(api().build(tarredDockerfile(), options));
|
||||
Iterable<String> splitted = Splitter.on("\n").split(buildStream.replace("\r", "").trim());
|
||||
String lastStreamedLine = Iterables.getLast(splitted).trim();
|
||||
String rawImageId = Iterables.getLast(Splitter.on("Successfully built ").split(lastStreamedLine));
|
||||
String imageId = rawImageId.substring(0, 11);
|
||||
Image image = api().inspectImage(imageId);
|
||||
api().deleteImage(image.id(), DeleteImageOptions.Builder.force(true));
|
||||
}
|
||||
|
||||
private RemoteApi api() {
|
||||
return api.getRemoteApi();
|
||||
private ContainerApi api() {
|
||||
return api.getContainerApi();
|
||||
}
|
||||
}
|
|
@ -16,50 +16,45 @@
|
|||
*/
|
||||
package org.jclouds.docker.features;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.domain.Config;
|
||||
import org.jclouds.docker.domain.Container;
|
||||
import org.jclouds.docker.domain.ContainerSummary;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.ListContainerOptions;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link org.jclouds.docker.DockerApi} class.
|
||||
* Mock tests for the {@link org.jclouds.docker.features.ContainerApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "RemoteApiMockTest")
|
||||
public class RemoteApiMockTest extends BaseDockerMockTest {
|
||||
@Test(groups = "unit", testName = "ContainerApiMockTest")
|
||||
public class ContainerApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
public void testListContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
|
||||
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
|
||||
try {
|
||||
Set<Container> containers = remoteApi.listContainers();
|
||||
List<ContainerSummary> containerSummaries = api.listContainers();
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
|
||||
assertEquals(containers.size(), 1);
|
||||
assertEquals(containerSummaries.size(), 1);
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -67,16 +62,14 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testListNonexistentContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
Set<Container> containers = remoteApi.listContainers();
|
||||
List<ContainerSummary> containerSummaries = api.listContainers();
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/containers/json");
|
||||
assertTrue(containers.isEmpty());
|
||||
assertTrue(containerSummaries.isEmpty());
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -86,14 +79,14 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testListAllContainers() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/containers.json")));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
Set<Container> containers = remoteApi.listContainers(ListContainerOptions.Builder.all(true));
|
||||
List<ContainerSummary> containerSummaries = api.listContainers(ListContainerOptions.Builder.all(true));
|
||||
assertRequestHasParameters(server.takeRequest(), "/containers/json", ImmutableMultimap.of("all", "true"));
|
||||
assertEquals(containers.size(), 1);
|
||||
assertEquals(containerSummaries.size(), 1);
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -101,20 +94,20 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testGetContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/container.json")));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
String containerId = "b03d4cd15b76f8876110615cdeed15eadf77c9beb408d62f1687dcc69192cd6d";
|
||||
try {
|
||||
Container container = remoteApi.inspectContainer(containerId);
|
||||
Container container = api.inspectContainer(containerId);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
|
||||
assertNotNull(container);
|
||||
assertNotNull(container.id(), containerId);
|
||||
assertNotNull(container.config());
|
||||
assertNotNull(container.hostConfig());
|
||||
assertEquals(container.name(), "/tender_lumiere");
|
||||
assertTrue(container.name().contains("/weave"));
|
||||
assertEquals(container.state().running(), true);
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -122,14 +115,14 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testGetNonExistingContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
String containerId = "notExisting";
|
||||
try {
|
||||
remoteApi.inspectContainer(containerId);
|
||||
Container container = api.inspectContainer(containerId);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/containers/" + containerId + "/json");
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -137,9 +130,8 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testCreateContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/container-creation.json")));
|
||||
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
Config containerConfig = Config.builder().cmd(ImmutableList.of("date"))
|
||||
.attachStdin(false)
|
||||
.attachStderr(true)
|
||||
|
@ -148,12 +140,12 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
.image("base")
|
||||
.build();
|
||||
try {
|
||||
Container container = remoteApi.createContainer("test", containerConfig);
|
||||
Container container = api.createContainer("test", containerConfig);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/create?name=test");
|
||||
assertNotNull(container);
|
||||
assertEquals(container.id(), "c6c74153ae4b1d1633d68890a68d89c40aa5e284a1ea016cbc6ef0e634ee37b2");
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -161,16 +153,15 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testRemoveContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(204));
|
||||
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
String containerId = "6d35806c1bd2b25cd92bba2d2c2c5169dc2156f53ab45c2b62d76e2d2fee14a9";
|
||||
|
||||
try {
|
||||
remoteApi.removeContainer(containerId);
|
||||
api.removeContainer(containerId);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/containers/" + containerId);
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -178,16 +169,16 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testRemoveNonExistingContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
String containerId = "nonExisting";
|
||||
try {
|
||||
remoteApi.removeContainer(containerId);
|
||||
api.removeContainer(containerId);
|
||||
fail("Remove container must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -195,13 +186,13 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testStartContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
remoteApi.startContainer("1");
|
||||
api.startContainer("1");
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/start");
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -209,17 +200,17 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testStartNonExistingContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
try {
|
||||
remoteApi.startContainer("1");
|
||||
api.startContainer("1");
|
||||
fail("Start container must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
}
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -227,13 +218,13 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testStopContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
remoteApi.stopContainer("1");
|
||||
api.stopContainer("1");
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/containers/1/stop");
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -241,97 +232,17 @@ public class RemoteApiMockTest extends BaseDockerMockTest {
|
|||
public void testStopNonExistingContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ContainerApi api = dockerApi.getContainerApi();
|
||||
try {
|
||||
remoteApi.stopContainer("1");
|
||||
api.stopContainer("1");
|
||||
fail("Stop container must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
api.close();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateImage() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
try {
|
||||
remoteApi.createImage(CreateImageOptions.Builder.fromImage("base"));
|
||||
assertRequestHasParameters(server.takeRequest(), "POST", "/images/create", ImmutableMultimap.of("fromImage",
|
||||
"base"));
|
||||
} finally {
|
||||
api.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateImageFailure() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
try {
|
||||
remoteApi.createImage(CreateImageOptions.Builder.fromImage("base"));
|
||||
fail("Create image must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
api.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteImage() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(204));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
try {
|
||||
remoteApi.deleteImage("1");
|
||||
assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/images/1");
|
||||
} finally {
|
||||
api.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteNotExistingImage() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
try {
|
||||
remoteApi.deleteImage("1");
|
||||
fail("Delete image must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
api.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildContainerUsingPayload() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi api = api(server.getUrl("/"));
|
||||
RemoteApi remoteApi = api.getRemoteApi();
|
||||
|
||||
File file = File.createTempFile("docker", "tmp");
|
||||
FileInputStream data = new FileInputStream(file);
|
||||
Payload payload = Payloads.newInputStreamPayload(data);
|
||||
payload.getContentMetadata().setContentLength(file.length());
|
||||
|
||||
try {
|
||||
remoteApi.build(payload, BuildOptions.NONE);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
|
||||
} finally {
|
||||
api.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", testName = "RemoteApiLiveTest", singleThreaded = true)
|
||||
public class ImageApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String DEFAULT_IMAGE = "busybox";
|
||||
private static final String DEFAULT_TAG = "ubuntu-14.04";
|
||||
|
||||
@Test
|
||||
public void testCreateImage() {
|
||||
InputStream createImageStream = api().createImage(CreateImageOptions.Builder.fromImage(DEFAULT_IMAGE).tag(DEFAULT_TAG));
|
||||
consumeStream(createImageStream);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateImage")
|
||||
public void testInspectImage() {
|
||||
assertNotNull(api.getImageApi().inspectImage(String.format("%s:%s", DEFAULT_IMAGE, DEFAULT_TAG)));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testInspectImage")
|
||||
public void testListImages() {
|
||||
assertNotNull(api().listImages());
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testListImages")
|
||||
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)));
|
||||
}
|
||||
|
||||
private ImageApi api() {
|
||||
return api.getImageApi();
|
||||
}
|
||||
|
||||
}
|
|
@ -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.features;
|
||||
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.CreateImageOptions;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
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();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ImageApi api = dockerApi.getImageApi();
|
||||
try {
|
||||
api.createImage(CreateImageOptions.Builder.fromImage("base"));
|
||||
assertRequestHasParameters(server.takeRequest(), "POST", "/images/create", ImmutableMultimap.of("fromImage", "base"));
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateImageFailure() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ImageApi api = dockerApi.getImageApi();
|
||||
try {
|
||||
api.createImage(CreateImageOptions.Builder.fromImage("base"));
|
||||
fail("Create image must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteImage() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(204));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ImageApi api = dockerApi.getImageApi();
|
||||
try {
|
||||
api.deleteImage("1");
|
||||
assertRequestHasCommonFields(server.takeRequest(), "DELETE", "/images/1");
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteNotExistingImage() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
ImageApi api = dockerApi.getImageApi();
|
||||
try {
|
||||
api.deleteImage("1");
|
||||
fail("Delete image must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
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 org.jclouds.docker.compute.BaseDockerApiLiveTest;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@Test(groups = "live", testName = "MiscApiLiveTest", singleThreaded = true)
|
||||
public class MiscApiLiveTest extends BaseDockerApiLiveTest {
|
||||
|
||||
private static final String API_VERSION = "1.15";
|
||||
private static final String VERSION = "1.3.0";
|
||||
private static final String GIT_COMMIT = "c78088f";
|
||||
private static final String GO_VERSION = "go1.3.3";
|
||||
private static final String KERNEL_VERSION = "3.16.4-tinycore64";
|
||||
private static final String ARCH = "amd64";
|
||||
private static final String OS = "linux";
|
||||
|
||||
private static String imageId;
|
||||
|
||||
@Test
|
||||
public void testVersion() {
|
||||
assertEquals(api().getVersion().apiVersion(), API_VERSION);
|
||||
assertEquals(api().getVersion().version(), VERSION);
|
||||
assertEquals(api().getVersion().gitCommit(), GIT_COMMIT);
|
||||
assertEquals(api().getVersion().goVersion(), GO_VERSION);
|
||||
assertEquals(api().getVersion().kernelVersion(), KERNEL_VERSION);
|
||||
assertEquals(api().getVersion().arch(), ARCH);
|
||||
assertEquals(api().getVersion().os(), OS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInfo() {
|
||||
assertNotNull(api().getInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildImageFromDockerfile() throws IOException, InterruptedException, URISyntaxException {
|
||||
BuildOptions options = BuildOptions.Builder.tag("testBuildImage").verbose(false).nocache(false);
|
||||
InputStream buildImageStream = api().build(tarredDockerfile(), options);
|
||||
String buildStream = consumeStream(buildImageStream);
|
||||
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);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
protected void tearDown() {
|
||||
if (imageId != null) {
|
||||
consumeStream(api.getImageApi().deleteImage(imageId));
|
||||
}
|
||||
}
|
||||
|
||||
private MiscApi api() {
|
||||
return api.getMiscApi();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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.features;
|
||||
|
||||
import com.squareup.okhttp.mockwebserver.MockResponse;
|
||||
import com.squareup.okhttp.mockwebserver.MockWebServer;
|
||||
import org.jclouds.docker.DockerApi;
|
||||
import org.jclouds.docker.domain.Info;
|
||||
import org.jclouds.docker.domain.Version;
|
||||
import org.jclouds.docker.internal.BaseDockerMockTest;
|
||||
import org.jclouds.docker.options.BuildOptions;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.jclouds.docker.compute.BaseDockerApiLiveTest.tarredDockerfile;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.fail;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
/**
|
||||
* Mock tests for the {@link org.jclouds.docker.features.MiscApi} class.
|
||||
*/
|
||||
@Test(groups = "unit", testName = "MiscApiMockTest")
|
||||
public class MiscApiMockTest extends BaseDockerMockTest {
|
||||
|
||||
private static final String API_VERSION = "1.15";
|
||||
private static final String VERSION = "1.3.0";
|
||||
private static final String GIT_COMMIT = "c78088f";
|
||||
private static final String GO_VERSION = "go1.3.3";
|
||||
private static final String KERNEL_VERSION = "3.16.4-tinycore64";
|
||||
private static final String ARCH = "amd64";
|
||||
private static final String OS = "linux";
|
||||
|
||||
public void testGetVersion() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/version.json")));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
MiscApi api = dockerApi.getMiscApi();
|
||||
try {
|
||||
Version version = api.getVersion();
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/version");
|
||||
assertNotNull(version);
|
||||
assertEquals(version.version(), VERSION);
|
||||
assertEquals(version.gitCommit(), GIT_COMMIT);
|
||||
assertEquals(version.apiVersion(), API_VERSION);
|
||||
assertEquals(version.goVersion(), GO_VERSION);
|
||||
assertEquals(version.kernelVersion(), KERNEL_VERSION);
|
||||
assertEquals(version.arch(), ARCH);
|
||||
assertEquals(version.os(), OS);
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetInfo() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setBody(payloadFromResource("/info.json")));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
MiscApi api = dockerApi.getMiscApi();
|
||||
|
||||
try {
|
||||
Info info = api.getInfo();
|
||||
assertRequestHasCommonFields(server.takeRequest(), "/info");
|
||||
assertNotNull(info);
|
||||
assertNotNull(info.containers());
|
||||
assertNotNull(info.debug());
|
||||
assertNotNull(info.driver());
|
||||
assertNotNull(info.executionDriver());
|
||||
assertNotNull(info.images());
|
||||
assertNotNull(info.indexServerAddress());
|
||||
assertNotNull(info.initPath());
|
||||
assertNotNull(info.iPv4Forwarding());
|
||||
assertNotNull(info.kernelVersion());
|
||||
assertNotNull(info.memoryLimit());
|
||||
assertNotNull(info.nEventsListener());
|
||||
assertNotNull(info.nFd());
|
||||
assertNotNull(info.nGoroutines());
|
||||
assertNotNull(info.swapLimit());
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
MiscApi api = dockerApi.getMiscApi();
|
||||
File dockerFile = File.createTempFile("docker", "tmp");
|
||||
try {
|
||||
api.build(tarredDockerfile(), BuildOptions.NONE);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
|
||||
} finally {
|
||||
dockerFile.delete();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildContainerUsingPayload() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(200));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
MiscApi api = dockerApi.getMiscApi();
|
||||
File file = File.createTempFile("docker", "tmp");
|
||||
FileInputStream data = new FileInputStream(file);
|
||||
Payload payload = Payloads.newInputStreamPayload(data);
|
||||
payload.getContentMetadata().setContentLength(file.length());
|
||||
|
||||
try {
|
||||
api.build(payload, BuildOptions.NONE);
|
||||
assertRequestHasCommonFields(server.takeRequest(), "POST", "/build");
|
||||
} finally {
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildNonexistentContainer() throws Exception {
|
||||
MockWebServer server = mockWebServer();
|
||||
server.enqueue(new MockResponse().setResponseCode(404));
|
||||
DockerApi dockerApi = api(server.getUrl("/"));
|
||||
MiscApi api = dockerApi.getMiscApi();
|
||||
File dockerFile = File.createTempFile("docker", "tmp");
|
||||
try {
|
||||
try {
|
||||
api.build(tarredDockerfile(), BuildOptions.NONE);
|
||||
fail("Build container must fail on 404");
|
||||
} catch (ResourceNotFoundException ex) {
|
||||
// Expected exception
|
||||
}
|
||||
} finally {
|
||||
dockerFile.delete();
|
||||
dockerApi.close();
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -58,8 +58,8 @@ public class BaseDockerMockTest {
|
|||
return ContextBuilder.newBuilder(provider)
|
||||
.credentials("clientid", "apikey")
|
||||
.endpoint(url.toString())
|
||||
.modules(modules)
|
||||
.overrides(setupProperties())
|
||||
.modules(modules)
|
||||
.overrides(setupProperties())
|
||||
.buildApi(DockerApi.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,16 +14,19 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM ubuntu:14.04
|
||||
MAINTAINER Sven Dowideit <SvenDowideit@docker.com>
|
||||
|
||||
FROM centos:6.4
|
||||
MAINTAINER Andrea Turli <andrea.turli@gmail.com>
|
||||
RUN apt-get update && apt-get install -y openssh-server
|
||||
RUN mkdir /var/run/sshd
|
||||
RUN echo 'root:screencast' | chpasswd
|
||||
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
||||
|
||||
# RUN yum -y groupinstall 'Development Tools'
|
||||
RUN yum -y install openssh-server openssh-clients
|
||||
# SSH login fix. Otherwise user is kicked off after login
|
||||
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
RUN chkconfig sshd on
|
||||
RUN service sshd start
|
||||
RUN echo 'root:password' | chpasswd
|
||||
ENV NOTVISIBLE "in users profile"
|
||||
RUN echo "export VISIBLE=now" >> /etc/profile
|
||||
|
||||
EXPOSE 22
|
||||
CMD ["/usr/sbin/sshd", "-D"]
|
|
@ -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
|
|
@ -1,81 +1,129 @@
|
|||
{
|
||||
"Args": [
|
||||
"-c",
|
||||
"yum -y install openssh-server openssh-clients"
|
||||
],
|
||||
"Config": {
|
||||
"AttachStderr": false,
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"yum -y install openssh-server openssh-clients"
|
||||
"Args": [
|
||||
"-iface",
|
||||
"ethwe",
|
||||
"-wait",
|
||||
"5",
|
||||
"-name",
|
||||
"7a:63:a2:39:7b:0f"
|
||||
],
|
||||
"CpuShares": 0,
|
||||
"Cpuset": "",
|
||||
"Domainname": "",
|
||||
"Entrypoint": [ "/usr/bin/sshd", "-d" ],
|
||||
"Env": [
|
||||
"HOME=/",
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"ExposedPorts": null,
|
||||
"Hostname": "9088c45a9592",
|
||||
"Image": "1e2d12a45cd57ae3fe3c31ede149d800aaf6a711c61646fad340080f531775c8",
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"NetworkDisabled": false,
|
||||
"OnBuild": [],
|
||||
"OpenStdin": false,
|
||||
"PortSpecs": null,
|
||||
"StdinOnce": false,
|
||||
"Tty": false,
|
||||
"User": "",
|
||||
"Volumes": null,
|
||||
"WorkingDir": ""
|
||||
},
|
||||
"Created": "2014-06-18T08:49:25.36448943Z",
|
||||
"Driver": "aufs",
|
||||
"ExecDriver": "native-0.2",
|
||||
"HostConfig": {
|
||||
"Binds": null,
|
||||
"ContainerIDFile": "",
|
||||
"Dns": null,
|
||||
"DnsSearch": null,
|
||||
"Links": null,
|
||||
"LxcConf": null,
|
||||
"NetworkMode": "",
|
||||
"PortBindings": null,
|
||||
"Privileged": false,
|
||||
"PublishAllPorts": false,
|
||||
"VolumesFrom": null
|
||||
},
|
||||
"HostnamePath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/hostname",
|
||||
"HostsPath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/hosts",
|
||||
"Id": "be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2",
|
||||
"Image": "1e2d12a45cd57ae3fe3c31ede149d800aaf6a711c61646fad340080f531775c8",
|
||||
"MountLabel": "",
|
||||
"Name": "/tender_lumiere",
|
||||
"NetworkSettings": {
|
||||
"Bridge": "docker0",
|
||||
"Gateway": "172.17.42.1",
|
||||
"IPAddress": "172.17.0.100",
|
||||
"IPPrefixLen": 16,
|
||||
"PortMapping": null,
|
||||
"Ports": {}
|
||||
},
|
||||
"Path": "/bin/sh",
|
||||
"ProcessLabel": "",
|
||||
"ResolvConfPath": "/mnt/sda1/var/lib/docker/containers/be1d295c091720abc9a3105219ab75a0a7367d74156cc6048aa599fcc7d650e2/resolv.conf",
|
||||
"State": {
|
||||
"ExitCode": 0,
|
||||
"FinishedAt": "0001-01-01T00:00:00Z",
|
||||
"Paused": false,
|
||||
"Pid": 16422,
|
||||
"Running": true,
|
||||
"StartedAt": "2014-06-18T08:49:25.63685385Z"
|
||||
},
|
||||
"Volumes": {},
|
||||
"VolumesRW": {}
|
||||
"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,
|
||||
"SecurityOpt": 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": null,
|
||||
"CapDrop": null,
|
||||
"ContainerIDFile": "",
|
||||
"Devices": [],
|
||||
"Dns": null,
|
||||
"DnsSearch": null,
|
||||
"ExtraHosts": null,
|
||||
"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": "docker0",
|
||||
"Gateway": "172.17.42.1",
|
||||
"IPAddress": "172.17.0.7",
|
||||
"IPPrefixLen": 16,
|
||||
"MacAddress": "02:42:ac:11:00:07",
|
||||
"PortMapping": null,
|
||||
"Ports": {
|
||||
"6783/tcp": [
|
||||
{
|
||||
"HostIp": "0.0.0.0",
|
||||
"HostPort": "6783"
|
||||
}
|
||||
],
|
||||
"6783/udp": [
|
||||
{
|
||||
"HostIp": "0.0.0.0",
|
||||
"HostPort": "6783"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Path": "/home/weave/weaver",
|
||||
"ProcessLabel": "",
|
||||
"ResolvConfPath": "/var/lib/docker/containers/6c9932f478bd761f32ddb54ed28ab42ab6fac6f2a279f561ea31503ee9d39524/resolv.conf",
|
||||
"State": {
|
||||
"ExitCode": 0,
|
||||
"FinishedAt": "0001-01-01T00:00:00Z",
|
||||
"Paused": false,
|
||||
"Pid": 3939,
|
||||
"Restarting": false,
|
||||
"Running": true,
|
||||
"StartedAt": "2014-10-31T17:00:21.802008706Z"
|
||||
},
|
||||
"Volumes": {},
|
||||
"VolumesRW": {}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"Containers": 0,
|
||||
"Debug": 1,
|
||||
"Driver": "aufs",
|
||||
"DriverStatus": [
|
||||
[
|
||||
"Root Dir",
|
||||
"/mnt/sda1/var/lib/docker/aufs"
|
||||
],
|
||||
[
|
||||
"Dirs",
|
||||
"15"
|
||||
]
|
||||
],
|
||||
"ExecutionDriver": "native-0.2",
|
||||
"IPv4Forwarding": 1,
|
||||
"Images": 15,
|
||||
"IndexServerAddress": "https://index.docker.io/v1/",
|
||||
"InitPath": "/usr/local/bin/docker",
|
||||
"InitSha1": "",
|
||||
"KernelVersion": "3.16.4-tinycore64",
|
||||
"MemoryLimit": 1,
|
||||
"NEventsListener": 0,
|
||||
"NFd": 10,
|
||||
"NGoroutines": 11,
|
||||
"OperatingSystem": "Boot2Docker 1.3.0 (TCL 5.4); master : a083df4 - Thu Oct 16 17:05:03 UTC 2014",
|
||||
"SwapLimit": 1
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"ApiVersion": "1.15",
|
||||
"Arch": "amd64",
|
||||
"GitCommit": "c78088f",
|
||||
"GoVersion": "go1.3.3",
|
||||
"KernelVersion": "3.16.4-tinycore64",
|
||||
"Os": "linux",
|
||||
"Version": "1.3.0"
|
||||
}
|
Loading…
Reference in New Issue