From 745ffef58081b406ef404f896f37310371c0ad85 Mon Sep 17 00:00:00 2001 From: Todd Nine Date: Mon, 2 Feb 2015 15:47:28 -0700 Subject: [PATCH 1/4] Added the ability to get a specific cube's docker Id in the interface. Added an internal dockerId. This allows multiple strategies to be configured. --- .../cube/impl/client/CubeConfiguration.java | 28 +++++++ .../cube/impl/client/CubeRegistrar.java | 11 ++- .../cube/impl/client/name/NameGenerator.java | 36 ++++++++ .../client/name/NameGeneratorFactory.java | 59 +++++++++++++ .../impl/client/name/StaticNameGenerator.java | 35 ++++++++ .../impl/client/name/UniqueNameGenerator.java | 62 ++++++++++++++ .../cube/impl/model/DockerCube.java | 36 ++++++-- .../cube/impl/util/BindingUtil.java | 4 +- .../client/name/NameGeneratorFactoryTest.java | 84 +++++++++++++++++++ .../client/name/StaticNameGeneratorTest.java | 22 +++++ .../client/name/UniqueNameGeneratorTest.java | 46 ++++++++++ .../cube/impl/model/DockerCubeTest.java | 3 +- ftest/src/test/resources/arquillian.xml | 2 + .../java/org/arquillian/cube/spi/Cube.java | 10 +++ 14 files changed, 425 insertions(+), 13 deletions(-) create mode 100644 docker/src/main/java/org/arquillian/cube/impl/client/name/NameGenerator.java create mode 100644 docker/src/main/java/org/arquillian/cube/impl/client/name/NameGeneratorFactory.java create mode 100644 docker/src/main/java/org/arquillian/cube/impl/client/name/StaticNameGenerator.java create mode 100644 docker/src/main/java/org/arquillian/cube/impl/client/name/UniqueNameGenerator.java create mode 100644 docker/src/test/java/org/arquillian/cube/impl/client/name/NameGeneratorFactoryTest.java create mode 100644 docker/src/test/java/org/arquillian/cube/impl/client/name/StaticNameGeneratorTest.java create mode 100644 docker/src/test/java/org/arquillian/cube/impl/client/name/UniqueNameGeneratorTest.java diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/CubeConfiguration.java b/docker/src/main/java/org/arquillian/cube/impl/client/CubeConfiguration.java index 08f346c97..c118dea5a 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/client/CubeConfiguration.java +++ b/docker/src/main/java/org/arquillian/cube/impl/client/CubeConfiguration.java @@ -17,11 +17,16 @@ public class CubeConfiguration { private static final String AUTO_START_CONTAINERS = "autoStartContainers"; private static final String SHOULD_ALLOW_TO_CONNECT_TO_RUNNING_CONTAINERS = "shouldAllowToConnectToRunningContainers"; + private static final String NAME_GENERATOR = "nameGenerator"; + private static final String NAME_GENERATOR_PREFIX = "nameGeneratorPrefix"; + private String dockerServerVersion; private String dockerServerUri; private String dockerRegistry; private boolean shouldAllowToConnectToRunningContainers = false; private String[] autoStartContainers = new String[0]; + private String nameGenerator; + private String getNameGeneratorPrefix; private Map dockerContainersContent; @@ -49,8 +54,22 @@ public String[] getAutoStartContainers() { return autoStartContainers; } + + public String getNameGenerator() { + return nameGenerator; + } + + + public String getGetNameGeneratorPrefix() { + return getNameGeneratorPrefix; + } + + @SuppressWarnings("unchecked") public static CubeConfiguration fromMap(Map map) { + + //TODO add provider parsing here + CubeConfiguration cubeConfiguration = new CubeConfiguration(); if (map.containsKey(DOCKER_VERSION)) { @@ -86,6 +105,15 @@ public static CubeConfiguration fromMap(Map map) { if(map.containsKey(SHOULD_ALLOW_TO_CONNECT_TO_RUNNING_CONTAINERS)) { cubeConfiguration.shouldAllowToConnectToRunningContainers = Boolean.parseBoolean(map.get(SHOULD_ALLOW_TO_CONNECT_TO_RUNNING_CONTAINERS)); } + + if(map.containsKey( NAME_GENERATOR )){ + cubeConfiguration.nameGenerator = map.get( NAME_GENERATOR ).trim(); + } + + if(map.containsKey( NAME_GENERATOR_PREFIX )){ + cubeConfiguration.getNameGeneratorPrefix = map.get( NAME_GENERATOR_PREFIX ).trim(); + } + return cubeConfiguration; } } diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/CubeRegistrar.java b/docker/src/main/java/org/arquillian/cube/impl/client/CubeRegistrar.java index 9b9331e9c..7c1eac48c 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/client/CubeRegistrar.java +++ b/docker/src/main/java/org/arquillian/cube/impl/client/CubeRegistrar.java @@ -2,6 +2,8 @@ import java.util.Map; +import org.arquillian.cube.impl.client.name.NameGenerator; +import org.arquillian.cube.impl.client.name.NameGeneratorFactory; import org.arquillian.cube.impl.docker.DockerClientExecutor; import org.arquillian.cube.impl.model.DockerCube; import org.arquillian.cube.impl.model.DockerCubeRegistry; @@ -19,19 +21,26 @@ public class CubeRegistrar { @SuppressWarnings("unchecked") public void register(@Observes DockerClientExecutor executor, CubeConfiguration configuration, Injector injector) { + final NameGenerator nameGenerator = NameGeneratorFactory.getGenerator( configuration ); + DockerCubeRegistry registry = new DockerCubeRegistry(); //TODO, add key here generation here Map containerConfigurations = configuration.getDockerContainersContent(); + + for(Map.Entry containerConfiguration : containerConfigurations.entrySet()) { + + registry.addCube( injector.inject( new DockerCube( containerConfiguration.getKey(), (Map)containerConfiguration.getValue(), - executor))); + executor, nameGenerator))); } + registryProducer.set(registry); } } diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGenerator.java b/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGenerator.java new file mode 100644 index 000000000..cbcf381af --- /dev/null +++ b/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGenerator.java @@ -0,0 +1,36 @@ +/* + * 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.arquillian.cube.impl.client.name; + + +/** + * Interface for generating names + */ +public interface NameGenerator { + + /** + * Get the name to use at runtime derived from the name assigned in the file + * @param assignedName + * @return + */ + String getName(final String assignedName); + +} diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGeneratorFactory.java b/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGeneratorFactory.java new file mode 100644 index 000000000..0ce63ef31 --- /dev/null +++ b/docker/src/main/java/org/arquillian/cube/impl/client/name/NameGeneratorFactory.java @@ -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.arquillian.cube.impl.client.name; + + +import org.arquillian.cube.impl.client.CubeConfiguration; + + +/** + * Return the name generator impl based on the configuration + */ +public class NameGeneratorFactory { + + /** + * Get the name generator for the configured option + * + * @param cubeConfiguration The cube configuration + * + * @return The NameGenerator instance to use when generating names. + */ + public static NameGenerator getGenerator( final CubeConfiguration cubeConfiguration ) { + + final String configurationName = cubeConfiguration.getNameGenerator(); + + //can't switch on a null + if ( configurationName == null ) { + return new StaticNameGenerator(); + } + + switch ( configurationName ) { + case StaticNameGenerator.TAG: + return new StaticNameGenerator(); + case UniqueNameGenerator.TAG: + return new UniqueNameGenerator( cubeConfiguration.getGetNameGeneratorPrefix() ); + default: + throw new IllegalArgumentException( + "The configuration of type '" + configurationName + "' is not a valid configuration. Use '" + + StaticNameGenerator.TAG + "' or '" + UniqueNameGenerator.TAG + "'." ); + } + } +} diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/name/StaticNameGenerator.java b/docker/src/main/java/org/arquillian/cube/impl/client/name/StaticNameGenerator.java new file mode 100644 index 000000000..0fc42aef0 --- /dev/null +++ b/docker/src/main/java/org/arquillian/cube/impl/client/name/StaticNameGenerator.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.arquillian.cube.impl.client.name; + + +/** + * Leaves the name as specified by the user + */ +public class StaticNameGenerator implements NameGenerator { + + public static final String TAG = "static"; + + @Override + public String getName( final String assignedName ) { + return assignedName; + } +} diff --git a/docker/src/main/java/org/arquillian/cube/impl/client/name/UniqueNameGenerator.java b/docker/src/main/java/org/arquillian/cube/impl/client/name/UniqueNameGenerator.java new file mode 100644 index 000000000..968e7dfe4 --- /dev/null +++ b/docker/src/main/java/org/arquillian/cube/impl/client/name/UniqueNameGenerator.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.arquillian.cube.impl.client.name; + + +import java.util.UUID; + + + +/** + * Generates the name from a prefix, name, and assigns a timeuuid for unique + */ +public class UniqueNameGenerator implements NameGenerator { + + + public static final String TAG = "unique"; + + private static final String DELIM = "_"; + + + private String prefix; + + + public UniqueNameGenerator( final String prefix ) { + + + if ( prefix == null ) { + throw new IllegalArgumentException( + "You must specify a name generator prefix when using the unique name generator " ); + } + + this.prefix = prefix; + } + + + @Override + public String getName( final String assignedName ) { + return prefix + DELIM + assignedName + DELIM + UUID.randomUUID(); + } + + + + +} diff --git a/docker/src/main/java/org/arquillian/cube/impl/model/DockerCube.java b/docker/src/main/java/org/arquillian/cube/impl/model/DockerCube.java index c1c67e5fc..996b659e2 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/model/DockerCube.java +++ b/docker/src/main/java/org/arquillian/cube/impl/model/DockerCube.java @@ -4,6 +4,7 @@ import java.util.logging.Logger; import org.arquillian.cube.impl.await.AwaitStrategyFactory; +import org.arquillian.cube.impl.client.name.NameGenerator; import org.arquillian.cube.impl.docker.DockerClientExecutor; import org.arquillian.cube.impl.util.BindingUtil; import org.arquillian.cube.spi.Binding; @@ -26,7 +27,13 @@ public class DockerCube implements Cube { private static final Logger log = Logger.getLogger(DockerCube.class.getName()); private State state = State.DESTROYED; + + //the identifier the user has assigned to this cube instance private String id; + + //The docker instance id. The unique instance name within docker may or may not match + //the user's supplied id if a unique naming scheme is used. + private String dockerId; private Binding binding = null; private Map configuration; @@ -36,8 +43,12 @@ public class DockerCube implements Cube { private DockerClientExecutor executor; - public DockerCube(String id, Map configuration, DockerClientExecutor executor) { + + + public DockerCube(String id, Map configuration, DockerClientExecutor executor, NameGenerator nameGenerator) { this.id = id; + this.dockerId = nameGenerator.getName(id); + this.configuration = configuration; this.executor = executor; } @@ -52,6 +63,13 @@ public String getId() { return id; } + + @Override + public String getDockerId() { + return dockerId; + } + + @Override public void create() throws CubeControlException { if(state != State.DESTROYED) { @@ -60,8 +78,8 @@ public void create() throws CubeControlException { try { lifecycle.fire(new BeforeCreate(id)); log.fine(String.format("Creating container with name %s and configuration %s.", id, configuration)); - executor.createContainer(id, configuration); - log.fine(String.format("Created container with id %s.", id)); + executor.createContainer( dockerId, configuration); + log.fine(String.format("Created container with id %s.", dockerId )); state = State.CREATED; lifecycle.fire(new AfterCreate(id)); } catch(Exception e) { @@ -77,10 +95,10 @@ public void start() throws CubeControlException { } try { lifecycle.fire(new BeforeStart(id)); - executor.startContainer(id, configuration); + executor.startContainer( dockerId, configuration); state = State.STARTED; if(!AwaitStrategyFactory.create(executor, this, configuration).await()) { - throw new IllegalArgumentException(String.format("Cannot connect to %s container", id)); + throw new IllegalArgumentException(String.format("Cannot connect to %s container", dockerId )); } lifecycle.fire(new AfterStart(id)); } catch(Exception e) { @@ -96,7 +114,7 @@ public void stop() throws CubeControlException { } try { lifecycle.fire(new BeforeStop(id)); - executor.stopContainer(id); + executor.stopContainer( dockerId ); state = State.STOPPED; lifecycle.fire(new AfterStop(id)); } catch(Exception e) { @@ -112,7 +130,7 @@ public void destroy() throws CubeControlException { } try { lifecycle.fire(new BeforeDestroy(id)); - executor.removeContainer(id); + executor.removeContainer( dockerId ); state = State.DESTROYED; lifecycle.fire(new AfterDestroy(id)); } catch(Exception e) { @@ -129,7 +147,7 @@ public Binding bindings() { if(state != State.STARTED && state != State.PRE_RUNNING) { throw new IllegalStateException("Can't get binding for cube " + id + " when status not " + State.STARTED + " or " + State.PRE_RUNNING + ". Status is " + state); } - binding = BindingUtil.binding(executor, id); + binding = BindingUtil.binding(executor, dockerId); return binding; } @@ -144,7 +162,7 @@ public void changeToPreRunning() { return; } - log.fine(String.format("Reusing prerunning container with name %s and configuration %s.", id, configuration)); + log.fine(String.format("Reusing prerunning container with name %s and configuration %s.", dockerId, configuration)); state = State.PRE_RUNNING; } } diff --git a/docker/src/main/java/org/arquillian/cube/impl/util/BindingUtil.java b/docker/src/main/java/org/arquillian/cube/impl/util/BindingUtil.java index 6b3004896..2c520fb29 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/util/BindingUtil.java +++ b/docker/src/main/java/org/arquillian/cube/impl/util/BindingUtil.java @@ -19,8 +19,8 @@ public final class BindingUtil { private BindingUtil() { } - public static Binding binding(DockerClientExecutor executor, String cubeId) { - InspectContainerResponse inspectResponse = executor.getDockerClient().inspectContainerCmd( cubeId ).exec(); + public static Binding binding(DockerClientExecutor executor, String dockerId) { + InspectContainerResponse inspectResponse = executor.getDockerClient().inspectContainerCmd( dockerId ).exec(); HostConfig hostConfig = inspectResponse.getHostConfig(); diff --git a/docker/src/test/java/org/arquillian/cube/impl/client/name/NameGeneratorFactoryTest.java b/docker/src/test/java/org/arquillian/cube/impl/client/name/NameGeneratorFactoryTest.java new file mode 100644 index 000000000..0f12ffce3 --- /dev/null +++ b/docker/src/test/java/org/arquillian/cube/impl/client/name/NameGeneratorFactoryTest.java @@ -0,0 +1,84 @@ +package org.arquillian.cube.impl.client.name; + + +import java.util.HashMap; +import java.util.Map; + +import org.arquillian.cube.impl.client.CubeConfiguration; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + + +/** + * + */ +public class NameGeneratorFactoryTest { + + @Test + public void unspecifiedUsesStaticName() { + final CubeConfiguration configuration = new CubeConfiguration(); + + final NameGenerator generator = NameGeneratorFactory.getGenerator( configuration ); + + assertTrue( "Correct instance returned", generator instanceof StaticNameGenerator ); + } + + + @Test + public void staticConfiguration() { + + final Map options = new HashMap() {{ + put( "nameGenerator", "static" ); + }}; + final CubeConfiguration configuration = CubeConfiguration.fromMap( options ); + + final NameGenerator generator = NameGeneratorFactory.getGenerator( configuration ); + + assertTrue( "Correct instance returned", generator instanceof StaticNameGenerator ); + } + + + @Test + public void uniqueConfiguration() { + + final Map options = new HashMap() {{ + put( "nameGenerator", "unique" ); + put( "nameGeneratorPrefix", "test" ); + }}; + + final CubeConfiguration configuration = CubeConfiguration.fromMap( options ); + + final NameGenerator generator = NameGeneratorFactory.getGenerator( configuration ); + + assertTrue( "Correct instance returned", generator instanceof UniqueNameGenerator ); + } + + + @Test( expected = IllegalArgumentException.class ) + public void uniqueConfigurationNoPrefix() { + + final Map options = new HashMap() {{ + put( "nameGenerator", "unique" ); + }}; + + final CubeConfiguration configuration = CubeConfiguration.fromMap( options ); + + //should throw illegal argument + NameGeneratorFactory.getGenerator( configuration ); + } + + + @Test( expected = IllegalArgumentException.class ) + public void invalidTypeName() { + + final Map options = new HashMap() {{ + put( "nameGenerator", "random stuff" ); + }}; + + final CubeConfiguration configuration = CubeConfiguration.fromMap( options ); + + //should throw illegal argument, not a type we support + NameGeneratorFactory.getGenerator( configuration ); + } +} diff --git a/docker/src/test/java/org/arquillian/cube/impl/client/name/StaticNameGeneratorTest.java b/docker/src/test/java/org/arquillian/cube/impl/client/name/StaticNameGeneratorTest.java new file mode 100644 index 000000000..c3667c900 --- /dev/null +++ b/docker/src/test/java/org/arquillian/cube/impl/client/name/StaticNameGeneratorTest.java @@ -0,0 +1,22 @@ +package org.arquillian.cube.impl.client.name; + + +import org.junit.Test; + +import static org.junit.Assert.*; + + +public class StaticNameGeneratorTest { + + @Test + public void testValidName(){ + final String expected = "testName"; + + final StaticNameGenerator generator = new StaticNameGenerator(); + + final String returned = generator.getName( expected ); + + assertEquals( "Same string should be returned", expected, returned ); + + } +} diff --git a/docker/src/test/java/org/arquillian/cube/impl/client/name/UniqueNameGeneratorTest.java b/docker/src/test/java/org/arquillian/cube/impl/client/name/UniqueNameGeneratorTest.java new file mode 100644 index 000000000..446069cfb --- /dev/null +++ b/docker/src/test/java/org/arquillian/cube/impl/client/name/UniqueNameGeneratorTest.java @@ -0,0 +1,46 @@ +package org.arquillian.cube.impl.client.name; + + +import org.junit.Test; + +import static org.junit.Assert.*; + + +public class UniqueNameGeneratorTest { + + @Test + public void nameGeneration(){ + + final String prefix = "prefix"; + final String name = "name"; + + final UniqueNameGenerator generator = new UniqueNameGenerator( prefix ); + + + final String returned = generator.getName( name ); + + final String expectedPrefix = prefix + "_"; + + assertTrue( "Prefix correct", returned.startsWith( expectedPrefix )); + + final String nameSection = returned.replace( expectedPrefix, "" ); + + + final String expectedName = name + "_"; + + assertTrue("Name correct", nameSection.startsWith( expectedName )); + + final String uuidSection = nameSection.replace( expectedName, "" ); + + //32 hex characters + 4 '-' chars + assertEquals("uuid section correct", 36, uuidSection.length()); + } + + + + @Test(expected = IllegalArgumentException.class) + public void noPrefixIllegal(){ + //throws an illegal argument + new UniqueNameGenerator( null ); + } +} diff --git a/docker/src/test/java/org/arquillian/cube/impl/model/DockerCubeTest.java b/docker/src/test/java/org/arquillian/cube/impl/model/DockerCubeTest.java index 3f3ca1635..4ef4ec503 100644 --- a/docker/src/test/java/org/arquillian/cube/impl/model/DockerCubeTest.java +++ b/docker/src/test/java/org/arquillian/cube/impl/model/DockerCubeTest.java @@ -2,6 +2,7 @@ import java.util.HashMap; +import org.arquillian.cube.impl.client.name.StaticNameGenerator; import org.arquillian.cube.impl.docker.DockerClientExecutor; import org.arquillian.cube.spi.event.lifecycle.AfterCreate; import org.arquillian.cube.spi.event.lifecycle.AfterDestroy; @@ -34,7 +35,7 @@ public class DockerCubeTest extends AbstractManagerTestBase { @Before public void setup() { - cube = injectorInst.get().inject(new DockerCube("test", new HashMap(), executor)); + cube = injectorInst.get().inject(new DockerCube("test", new HashMap(), executor, new StaticNameGenerator()) ); } @Test diff --git a/ftest/src/test/resources/arquillian.xml b/ftest/src/test/resources/arquillian.xml index 0f841e8c1..688237dba 100644 --- a/ftest/src/test/resources/arquillian.xml +++ b/ftest/src/test/resources/arquillian.xml @@ -11,6 +11,8 @@ ${docker.api.version} ${docker.api.url} ${arquillian.cube.autostart} + unique + cube tomcat_default: image: tutum/tomcat:7.0 diff --git a/spi/src/main/java/org/arquillian/cube/spi/Cube.java b/spi/src/main/java/org/arquillian/cube/spi/Cube.java index 757574090..2911b0246 100644 --- a/spi/src/main/java/org/arquillian/cube/spi/Cube.java +++ b/spi/src/main/java/org/arquillian/cube/spi/Cube.java @@ -18,8 +18,18 @@ public enum State { State state(); + /** + * Return the user assigned Id of this cube instance + * @return + */ String getId(); + /** + * Get the id (name) used within docker for this runtime + * @return + */ + String getDockerId(); + void create() throws CubeControlException; void start() throws CubeControlException; From 016def39eb619654594beea55c1d89d0ea39808b Mon Sep 17 00:00:00 2001 From: Todd Nine Date: Tue, 3 Feb 2015 09:26:31 -0700 Subject: [PATCH 2/4] Updated readme --- README.adoc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.adoc b/README.adoc index 69f472535..77e4f4fff 100644 --- a/README.adoc +++ b/README.adoc @@ -54,6 +54,25 @@ Go version (server): go1.3.1 If you cannot see the client and server versions then it means that something is wrong with the _Docker_ installation. +== Using an external Docker server + +When using an external docker server, such as boot2docker, additional configuration on the client is required as of 1.0.0.Alpha3. The following properties will need to be set within the user's maven profile. + +[source, xml] +1.12 +[boot2docker or docker host] +https://${docker.host}:2376 + + + +When using tls, the file ~/.docker.io.properties will also need to be installed with these options. + +[source, properties] +docker.io.url=https://[boot2docker or docker host]:2376 +docker.io.version=1.12 +docker.io.dockerCertPath=[path to docker certs provided on boot2docker start] + + == Basic Example After having a _Docker_ server installed we can start using *Arquillian Cube*. From a3ba04bdea7e77014261ed8ab792621c574951c1 Mon Sep 17 00:00:00 2001 From: Todd Nine Date: Thu, 5 Feb 2015 11:06:23 -0700 Subject: [PATCH 3/4] Fixes new polling to use the docker Id Adds error checking on the docker pull command. --- .../cube/impl/await/PollingAwaitStrategy.java | 2 +- .../cube/impl/docker/DockerClientExecutor.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docker/src/main/java/org/arquillian/cube/impl/await/PollingAwaitStrategy.java b/docker/src/main/java/org/arquillian/cube/impl/await/PollingAwaitStrategy.java index d8724df8a..9777ca95a 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/await/PollingAwaitStrategy.java +++ b/docker/src/main/java/org/arquillian/cube/impl/await/PollingAwaitStrategy.java @@ -103,7 +103,7 @@ public boolean await() { break; case "sscommand": { - if(!Ping.ping(dockerClientExecutor, cube.getId(), resolveCommand("ss", ports.getExposedPort()), this.pollIterations, this.sleepPollTime, this.timeUnit)) { + if(!Ping.ping(dockerClientExecutor, cube.getDockerId(), resolveCommand("ss", ports.getExposedPort()), this.pollIterations, this.sleepPollTime, this.timeUnit)) { return false; } } diff --git a/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java b/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java index b34e6ff2c..66c292588 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java +++ b/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java @@ -458,16 +458,23 @@ public void pullImage(String imageName) { } int tagSeparator = imageName.indexOf(TAG_SEPARATOR); + if (tagSeparator > 0) { - pullImageCmd.withRepository(imageName.substring(0, tagSeparator)); - pullImageCmd.withTag(imageName.substring(tagSeparator + 1)); + final String repository = imageName.substring(0, tagSeparator); + final String tag = imageName.substring( tagSeparator + 1 ); + pullImageCmd.withRepository(repository); + pullImageCmd.withTag(tag); } InputStream exec = pullImageCmd.exec(); // To wait until image is pull we need to listen input stream until it is closed by the server // At this point we can be sure that image is already pulled. - IOUtil.asString(exec); + final String pullResults = IOUtil.asString(exec); + + if(pullResults == null || pullResults.contains( "error" )){ + throw new RuntimeException( "Unable to pull image. \n" + pullResults ); + } } public String execStart(String containerId, String... commands) { From 735e5d6806d11b1f8247f9f39a1d3f29088dca70 Mon Sep 17 00:00:00 2001 From: Todd Nine Date: Thu, 5 Feb 2015 11:37:40 -0700 Subject: [PATCH 4/4] Changed configuration to be more declarative with less variables. Changed error assertion to only check for valid output. Every other response is an error --- .../cube/impl/docker/DockerClientExecutor.java | 6 ++++-- ftest/pom.xml | 4 ++-- ftest/src/test/resources/arquillian.xml | 12 ++++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java b/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java index 66c292588..d152fa0e7 100644 --- a/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java +++ b/docker/src/main/java/org/arquillian/cube/impl/docker/DockerClientExecutor.java @@ -472,8 +472,10 @@ public void pullImage(String imageName) { // At this point we can be sure that image is already pulled. final String pullResults = IOUtil.asString(exec); - if(pullResults == null || pullResults.contains( "error" )){ - throw new RuntimeException( "Unable to pull image. \n" + pullResults ); + final String expectedOutput = "Status: Downloaded newer image for " + imageName; + + if(pullResults == null || !pullResults.contains( expectedOutput )){ + throw new RuntimeException( "Unable to pull image. Expected output '" + expectedOutput + "' to be returned. Instead this was returned \n" + pullResults ); } } diff --git a/ftest/pom.xml b/ftest/pom.xml index 2e055f9f8..5f19dded7 100644 --- a/ftest/pom.xml +++ b/ftest/pom.xml @@ -15,8 +15,8 @@ 8.1.0.Final 1.0.0.Alpha1 1.12 - http://localhost:2375 - localhost + localhost + http://${docker.api.host}:2375 diff --git a/ftest/src/test/resources/arquillian.xml b/ftest/src/test/resources/arquillian.xml index 688237dba..cd65de3e9 100644 --- a/ftest/src/test/resources/arquillian.xml +++ b/ftest/src/test/resources/arquillian.xml @@ -19,14 +19,14 @@ exposedPorts: [8089/tcp] await: strategy: polling - env: [TOMCAT_PASS=mypass, JAVA_OPTS=-Djava.rmi.server.hostname=${docker.tomcat.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] + env: [TOMCAT_PASS=mypass, JAVA_OPTS=-Djava.rmi.server.hostname=${docker.api.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] portBindings: [8089/tcp, 8088/tcp, 8081->8080/tcp] tomcat: image: tutum/tomcat:7.0 exposedPorts: [8089/tcp] await: strategy: polling - env: [TOMCAT_PASS=mypass, JAVA_OPTS=-Djava.rmi.server.hostname=${docker.tomcat.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] + env: [TOMCAT_PASS=mypass, JAVA_OPTS=-Djava.rmi.server.hostname=${docker.api.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] portBindings: [8089/tcp, 8088/tcp, 8081->8080/tcp] tomcat_dockerfile: buildImage: @@ -35,7 +35,7 @@ remove: true await: strategy: polling - env: [JAVA_OPTS=-Djava.rmi.server.hostname=${docker.tomcat.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] + env: [JAVA_OPTS=-Djava.rmi.server.hostname=${docker.api.host} -Dcom.sun.management.jmxremote.rmi.port=8088 -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false] portBindings: [8089/tcp, 8088/tcp, 8081->8080/tcp] wildfly: buildImage: @@ -69,7 +69,7 @@ - ${docker.tomcat.host} + ${docker.api.host} 8081 admin mypass @@ -77,14 +77,14 @@ - ${docker.tomcat.host} + ${docker.api.host} admin mypass - ${docker.tomcat.host} + ${docker.api.host} 8081 admin mypass