no_entry: Move docker classes to new location

Signed-off-by: Andrew Donald Kennedy <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/e890c003
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/e890c003
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/e890c003

Branch: refs/heads/master
Commit: e890c0037068423e573cd77d1ffae30ebe350d47
Parents: 2a1b1fa
Author: CloudsoftOps <[email protected]>
Authored: Thu May 18 17:42:53 2017 +0100
Committer: Andrew Donald Kennedy <[email protected]>
Committed: Fri May 19 14:03:37 2017 +0100

----------------------------------------------------------------------
 .../entity/docker/DockerContainer.java          |  73 ++++++
 .../entity/docker/DockerContainerImpl.java      |  71 ++++++
 .../location/docker/DockerJcloudsLocation.java  | 185 ++++++++++++++
 .../location/docker/DockerLocationResolver.java |  71 ++++++
 .../docker/DockerJcloudsLocationLiveTest.java   | 252 +++++++++++++++++++
 .../docker/DockerLocationResolverTest.java      | 100 ++++++++
 .../dockercontainer/DockerContainer.java        |  73 ------
 .../dockercontainer/DockerContainerImpl.java    |  71 ------
 .../dockerlocation/DockerJcloudsLocation.java   | 185 --------------
 .../dockerlocation/DockerLocationResolver.java  |  71 ------
 .../DockerJcloudsLocationLiveTest.java          | 252 -------------------
 .../DockerLocationResolverTest.java             | 100 --------
 12 files changed, 752 insertions(+), 752 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainer.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainer.java
 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainer.java
new file mode 100644
index 0000000..ef012c3
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainer.java
@@ -0,0 +1,73 @@
+package io.cloudsoft.amp.containerservice.dockercontainer;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.BasicConfigInheritance;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.config.MapConfigKey;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * The DockerContainer type is for easily deploying any docker image from the
+ * image repository set on the target swarm or docker-engine based location
+ * <p>
+ * Example YAML is shown below. Note the different types of the {@code env}
+ * key in the location config and the {@code docker.container.environment}
+ * key on the entity. The entity environment variables will override any
+ * environment configured on the location. To specify environment variables
+ * that will be set when executing SSH commands against the container you
+ * should use the {@link SoftwareProcess#SHELL_ENVIRONMENT shell.env} key.
+ * <p>
+ * <pre>{@code location:
+ *   docker:
+ *     endpoint: "https://52.29.59.193:3376";
+ *     identity: "~/.certs/cert.pem"
+ *     credential: "~/.certs/key.pem"
+ *     templateOptions:
+ *       networkMode: "brooklyn"
+ *     env:
+ *       - "HTTP_CONFIG_ROOT=/var/httpd"
+ *       - "USE_DEFAULTS=true"
+ * services:
+ *   - type: io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer
+ *     brooklyn.config:
+ *       docker.container.imageName: "apache/httpd:latest"
+ *       docker.container.disableSsh: true
+ *       docker.container.inboundPorts:
+ *         - "8080-8081"
+ *       docker.container.environment:
+ *         ENABLE_JMX: false
+ *         ENABLE_SHUTDOWN: false
+ * }</pre>
+ */
+@ImplementedBy(DockerContainerImpl.class)
+public interface DockerContainer extends SoftwareProcess {
+
+    ConfigKey<Boolean> DISABLE_SSH =
+            ConfigKeys.newBooleanConfigKey(
+                    "docker.container.disableSsh",
+                    "Skip checks such as ssh for when docker image doesn't 
allow ssh",
+                    Boolean.TRUE);
+
+    ConfigKey<String> IMAGE_NAME =
+            ConfigKeys.newStringConfigKey(
+                    "docker.container.imageName",
+                    "Image name to pull from docker hub");
+
+    @SuppressWarnings("serial")
+    ConfigKey<Iterable<String>> INBOUND_TCP_PORTS =
+            ConfigKeys.newConfigKey(
+                    new TypeToken<Iterable<String>>() {},
+                    "docker.container.inboundPorts",
+                    "List of ports, that the docker image opens, to be made 
public");
+
+    MapConfigKey<Object> CONTAINER_ENVIRONMENT = new 
MapConfigKey.Builder<Object>(Object.class, "docker.container.environment")
+            .description("Environment variables to set on container startup")
+            .defaultValue(ImmutableMap.<String, Object>of())
+            .typeInheritance(BasicConfigInheritance.DEEP_MERGE)
+            
.runtimeInheritance(BasicConfigInheritance.NOT_REINHERITED_ELSE_DEEP_MERGE)
+            .build();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainerImpl.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainerImpl.java
 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainerImpl.java
new file mode 100644
index 0000000..790985f
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/entity/docker/DockerContainerImpl.java
@@ -0,0 +1,71 @@
+package io.cloudsoft.amp.containerservice.dockercontainer;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.location.PortRanges;
+import org.apache.brooklyn.core.network.OnPublicNetworkEnricher;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
+import org.apache.brooklyn.util.collections.MutableList;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+
+public class DockerContainerImpl extends EmptySoftwareProcessImpl implements 
DockerContainer {
+
+   @Override
+   public void init() {
+      super.init();
+
+      String imageName = config().get(DockerContainer.IMAGE_NAME);
+      if (!Strings.isNullOrEmpty(imageName)) {
+         config().set(PROVISIONING_PROPERTIES.subKey("imageId"), imageName);
+      }
+
+      if (Boolean.TRUE.equals(config().get(DockerContainer.DISABLE_SSH))) {
+         config().set(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, 
true);
+         config().set(PROVISIONING_PROPERTIES.subKey("useJcloudsSshInit"), 
false);
+         config().set(PROVISIONING_PROPERTIES.subKey("waitForSshable"), false);
+         
config().set(PROVISIONING_PROPERTIES.subKey("pollForFirstReachableAddress"), 
false);
+         config().set(EmptySoftwareProcessImpl.USE_SSH_MONITORING, false);
+      }
+
+      ImmutableSet.Builder<AttributeSensor<Integer>> builder = 
ImmutableSet.builder();
+      List<String> portRanges = 
MutableList.copyOf(config().get(DockerContainer.INBOUND_TCP_PORTS));
+      for (String portRange : portRanges) {
+         Iterator<Integer> iterator = 
PortRanges.fromString(portRange).iterator();
+         while (iterator.hasNext()) {
+            Integer port = iterator.next();
+            AttributeSensor<Integer> element = 
Sensors.newIntegerSensor("docker.port." + port);
+            sensors().set(element, port);
+            builder.add(element);
+         }
+      }
+
+      
enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class).configure(OnPublicNetworkEnricher.SENSORS,
 builder.build()));
+   }
+
+   @Override
+   protected void disconnectSensors() {
+      if(isSshMonitoringEnabled()) {
+         disconnectServiceUpIsRunning();
+      }
+      super.disconnectSensors();
+   }
+
+   @Override
+   protected void connectSensors() {
+      super.connectSensors();
+      if (isSshMonitoringEnabled()) {
+         connectServiceUpIsRunning();
+      } else {
+         sensors().set(Attributes.SERVICE_UP, true);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocation.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocation.java
 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocation.java
new file mode 100644
index 0000000..ecf3214
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocation.java
@@ -0,0 +1,185 @@
+package io.cloudsoft.amp.containerservice.dockerlocation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.location.LocationConfigKeys;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.apache.brooklyn.util.text.Strings;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.docker.compute.options.DockerTemplateOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer;
+
+/**
+ * For provisioning docker containers, using the jclouds-docker integration.
+ * 
+ * This adds special support for default Cloudsoft images. If the image 
description matches our 
+ * cloudsoft regexes, then auto-generate a password and pass that in as 
+ * {@code CLOUDSOFT_ROOT_PASSWORD} when launching the container. That will 
then be used as the 
+ * {@link DockerTemplateOptions#getLoginPassword()}.
+ * 
+ * Also, if no image is specified then this will set the default to 
"cloudsoft/centos:7"
+ * (see https://hub.docker.com/r/cloudsoft/centos/).
+ */
+public class DockerJcloudsLocation extends JcloudsLocation {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(DockerJcloudsLocation.class);
+
+    public static final ConfigKey<Boolean> INJECT_LOGIN_CREDENTIAL = 
ConfigKeys.newBooleanConfigKey(
+            "injectLoginCredential", 
+            "Whether to inject login credentials (if null, will infer from 
image choice)", 
+            null);
+
+    public static final ConfigKey<String> DEFAULT_IMAGE_DESCRIPTION_REGEX = 
ConfigKeys.newStringConfigKey(
+            "defaultImageDescriptionRegex", 
+            "The default image description to use, if no other image 
preferences are supplied",
+            "cloudsoft/centos:7");
+
+    /**
+     * The regex for the image descriptions that support us injecting login 
credentials.
+     */
+    private static final List<String> 
IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS = ImmutableList.of(
+            "cloudsoft/centos.*",
+            "cloudsoft/ubuntu.*");
+
+    private static final List<ImageMetadata> DEFAULT_IMAGES = ImmutableList.of(
+            new ImageMetadata(OsFamily.CENTOS, "7", "cloudsoft/centos:7"),
+            new ImageMetadata(OsFamily.UBUNTU, "14.04", 
"cloudsoft/ubuntu:14.04"),
+            new ImageMetadata(OsFamily.UBUNTU, "16.04", 
"cloudsoft/ubuntu:16.04"));
+
+    private static class ImageMetadata {
+        private final OsFamily osFamily;
+        private final String osVersion;
+        private final String imageDescription;
+        
+        public ImageMetadata(OsFamily osFamily, String osVersion, String 
imageDescription) {
+            this.osFamily = checkNotNull(osFamily, "osFamily");
+            this.osVersion = checkNotNull(osVersion, "osVersion");
+            this.imageDescription = checkNotNull(imageDescription, 
"imageDescription");
+        }
+        
+        public boolean matches(@Nullable OsFamily osFamily, @Nullable String 
osVersionRegex) {
+            if (osFamily != null && osFamily != this.osFamily) return false;
+            if (osVersionRegex != null && !osVersion.matches(osVersionRegex)) 
return false;
+            return true;
+        }
+        
+        public String getImageDescription() {
+            return imageDescription;
+        }
+    }
+
+    @Override
+    protected MachineLocation obtainOnce(ConfigBag setup) throws 
NoMachinesAvailableException {
+        // Use the provider name that jclouds expects; rely on resolver to 
have validated this.
+        setup.configure(JcloudsLocation.CLOUD_PROVIDER, "docker");
+        
+        // Inject default image, if absent
+        String imageId = setup.get(JcloudsLocation.IMAGE_ID);
+        String imageNameRegex = setup.get(JcloudsLocation.IMAGE_NAME_REGEX);
+        String imageDescriptionRegex = 
setup.get(JcloudsLocation.IMAGE_DESCRIPTION_REGEX);
+        String defaultImageDescriptionRegex = 
setup.get(DEFAULT_IMAGE_DESCRIPTION_REGEX);
+        OsFamily osFamily = setup.get(OS_FAMILY);
+        String osVersionRegex = setup.get(OS_VERSION_REGEX);
+        
+        if (Strings.isBlank(imageId) && Strings.isBlank(imageNameRegex) && 
Strings.isBlank(imageDescriptionRegex)) {
+            if (osFamily != null || osVersionRegex != null) {
+                for (ImageMetadata imageMetadata : DEFAULT_IMAGES) {
+                    if (imageMetadata.matches(osFamily, osVersionRegex)) {
+                        String imageDescription = 
imageMetadata.getImageDescription();
+                        LOG.debug("Setting default image regex to {}, for 
obtain call in {}; removing osFamily={} and osVersionRegex={}", 
+                                new Object[] {imageDescription, this, 
osFamily, osVersionRegex});
+                        
setup.configure(JcloudsLocation.IMAGE_DESCRIPTION_REGEX, imageDescription);
+                        setup.configure(OS_FAMILY, null);
+                        setup.configure(OS_VERSION_REGEX, null);
+                        break;
+                    }
+                }
+            } else if (Strings.isNonBlank(defaultImageDescriptionRegex)) {
+                LOG.debug("Setting default image regex to {}, for obtain call 
in {}", defaultImageDescriptionRegex, this);
+                setup.configure(JcloudsLocation.IMAGE_DESCRIPTION_REGEX, 
defaultImageDescriptionRegex);
+            }
+        }
+        
+        return super.obtainOnce(setup);
+    }
+    
+    @Override
+    public Template buildTemplate(ComputeService computeService, ConfigBag 
config, Collection<JcloudsLocationCustomizer> customizers) {
+        String loginUser = config.get(JcloudsLocation.LOGIN_USER);
+        String loginPassword = config.get(JcloudsLocation.LOGIN_USER_PASSWORD);
+        String loginKeyFile = 
config.get(JcloudsLocation.LOGIN_USER_PRIVATE_KEY_FILE);
+        String loginKeyData = 
config.get(JcloudsLocation.LOGIN_USER_PRIVATE_KEY_DATA);
+
+        Template template = super.buildTemplate(computeService, config, 
customizers);
+        DockerTemplateOptions templateOptions = (DockerTemplateOptions) 
template.getOptions();
+        Image image = template.getImage();
+        List<String> env = MutableList.copyOf(templateOptions.getEnv());
+
+        // Inject login credentials, if required
+        Boolean injectLoginCredentials = config.get(INJECT_LOGIN_CREDENTIAL);
+        if (injectLoginCredentials == null) {
+            String imageDescription = image.getDescription();
+            for (String regex : 
IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS) {
+                if (imageDescription != null && 
imageDescription.matches(regex)) {
+                    injectLoginCredentials = true;
+                    break;
+                }
+            }
+        }
+        if (Strings.isBlank(loginUser) && Strings.isBlank(loginPassword) && 
Strings.isBlank(loginKeyFile) && Strings.isBlank(loginKeyData)) {
+            if (Boolean.TRUE.equals(injectLoginCredentials)) {
+                loginUser = "root";
+                loginPassword = Identifiers.makeRandomPassword(12);
+                templateOptions.overrideLoginUser(loginUser);
+                templateOptions.overrideLoginPassword(loginPassword);
+
+                env.add("CLOUDSOFT_ROOT_PASSWORD="+loginPassword);
+            }
+        }
+
+        Entity context = validateCallerContext(config);
+        Map<String,Object> containerEnv = 
MutableMap.copyOf(context.config().get(DockerContainer.CONTAINER_ENVIRONMENT));
+        for (Map.Entry<String,String> entry : 
Maps.transformValues(containerEnv, Functions.toStringFunction()).entrySet()) {
+            env.add(String.format("%s=%s", entry.getKey(), entry.getValue()));
+        }
+        templateOptions.env(env);
+
+        return template;
+    }
+
+
+    private Entity validateCallerContext(ConfigBag setup) {
+        // Lookup entity flags
+        Object callerContext = setup.get(LocationConfigKeys.CALLER_CONTEXT);
+        if (callerContext == null || !(callerContext instanceof Entity)) {
+            throw new IllegalStateException("Invalid caller context: " + 
callerContext);
+        }
+        return (Entity) callerContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerLocationResolver.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerLocationResolver.java
 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerLocationResolver.java
new file mode 100644
index 0000000..d6c8c99
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/docker/DockerLocationResolver.java
@@ -0,0 +1,71 @@
+package io.cloudsoft.amp.containerservice.dockerlocation;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationResolver;
+import org.apache.brooklyn.core.location.AbstractLocationResolver;
+import org.apache.brooklyn.core.location.LocationConfigUtils;
+import 
org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties;
+import 
org.apache.brooklyn.location.jclouds.JcloudsPropertiesFromBrooklynProperties;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Locations starting with the given prefix (@code "docker") will use this 
resolver, to instantiate
+ * a {@link DockerJcloudsLocation}.
+ * 
+ * We ensure that config will be picked up from brooklyn.properties using the 
appropriate precedence:
+ * <ol>
+ *   <li>named location config
+ *   <li>Prefix {@code brooklyn.location.docker.}
+ *   <li>Prefix {@code brooklyn.jclouds.docker.}
+ *   <li>Prefix {@code brooklyn.jclouds.}
+ * </ol>
+ */
+public class DockerLocationResolver extends AbstractLocationResolver 
implements LocationResolver {
+
+    public static final Logger log = 
LoggerFactory.getLogger(DockerLocationResolver.class);
+    
+    public static final String PREFIX = "docker";
+
+    @Override
+    public boolean isEnabled() {
+        return LocationConfigUtils.isResolverPrefixEnabled(managementContext, 
getPrefix());
+    }
+    
+    @Override
+    public String getPrefix() {
+        return PREFIX;
+    }
+    
+    @Override
+    protected Class<? extends Location> getLocationType() {
+        return DockerJcloudsLocation.class;
+    }
+
+    @Override
+    protected SpecParser getSpecParser() {
+        return new 
AbstractLocationResolver.SpecParser(getPrefix()).setExampleUsage("\"docker\"");
+    }
+
+    @Override
+    protected Map<String, Object> getFilteredLocationProperties(String 
provider, String namedLocation, Map<String, ?> prioritisedProperties, 
Map<String, ?> globalProperties) {
+        Map<String, Object> dockerConf = new 
LocationPropertiesFromBrooklynProperties().getLocationProperties(getPrefix(), 
namedLocation, globalProperties);
+        
+        Object providerInConf = dockerConf.get("provider");
+        if (providerInConf != null && !provider.equals(providerInConf)) {
+            throw new IllegalArgumentException(provider+" location configured 
with provider '"+providerInConf+"', but must be blank or '"+provider+"'");
+        }
+
+        String providerOrApi = "docker";
+        String regionName = (String) prioritisedProperties.get("region");
+        Map<String, Object> jcloudsConf = new 
JcloudsPropertiesFromBrooklynProperties().getJcloudsProperties(providerOrApi, 
regionName, namedLocation, globalProperties);
+        return MutableMap.<String, Object>builder()
+                .putAll(jcloudsConf)
+                .putAll(dockerConf)
+                .put("provider", providerOrApi)
+                .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocationLiveTest.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocationLiveTest.java
 
b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocationLiveTest.java
new file mode 100644
index 0000000..eb64173
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerJcloudsLocationLiveTest.java
@@ -0,0 +1,252 @@
+package io.cloudsoft.amp.containerservice.dockerlocation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.location.jclouds.BasicJcloudsLocationCustomizer;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsLocationConfig;
+import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
+import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.os.Os;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.docker.compute.options.DockerTemplateOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * TODO For these tests to pass, they need on the classpath the patch file(s) 
from AMP.
+ * 
+ * Assumes that a pre-existing swarm endpoint is available. See system 
properties and the defaults
+ * below.
+ */
+public class DockerJcloudsLocationLiveTest extends BrooklynAppLiveTestSupport {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(DockerJcloudsLocationLiveTest.class);
+    
+    private static final String SWARM_ENDPOINT = 
System.getProperty("test.amp.docker.swarmEndpoint", 
"https://10.104.0.162:3376/";);
+    private static final String IDENTITY_FILE_PATH = 
System.getProperty("test.amp.docker.identity", 
Os.tidyPath("~/.docker/.certs/cert.pem"));
+    private static final String CREDENTIAL_FILE_PATH = 
System.getProperty("test.amp.docker.credential", 
Os.tidyPath("~/.docker/.certs/key.pem"));
+    private static final String SWARM_NETWORK_NAME = 
System.getProperty("test.amp.docker.networkName", Os.tidyPath("brooklyn"));
+    
+    protected DockerJcloudsLocation loc;
+    protected List<MachineLocation> machines;
+    protected DockerTemplateOptions templateOptions;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        machines = Lists.newCopyOnWriteArrayList();
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    @Override
+    public void tearDown() throws Exception {
+        for (MachineLocation machine : machines) {
+            try {
+                loc.release(machine);
+            } catch (Exception e) {
+                LOG.error("Error releasing machine "+machine+" in location 
"+loc, e);
+            }
+        }
+        super.tearDown();
+    }
+    
+    protected DockerJcloudsLocation newDockerLocation(Map<String, ?> flags) 
throws Exception {
+        JcloudsLocationCustomizer locationCustomizer = new 
BasicJcloudsLocationCustomizer() {
+            @Override
+            public void customize(JcloudsLocation location, ComputeService 
computeService, TemplateOptions templateOptions) {
+                DockerJcloudsLocationLiveTest.this.templateOptions = 
(DockerTemplateOptions) templateOptions;
+            }
+        };
+        Map<String, ?> templateOptionsOverrides = (Map<String, ?>) 
flags.get(JcloudsLocation.TEMPLATE_OPTIONS.getName());
+        Map<String,?> templateOptions = MutableMap.<String, Object>builder()
+                .put("networkMode", SWARM_NETWORK_NAME)
+                .putAll(templateOptionsOverrides != null ? 
templateOptionsOverrides : ImmutableMap.<String, Object>of())
+                .build();
+        Map<String,?> allFlags = MutableMap.<String,Object>builder()
+                .put("identity", IDENTITY_FILE_PATH)
+                .put("credential", CREDENTIAL_FILE_PATH)
+                .put("endpoint", SWARM_ENDPOINT)
+                .put("tags", ImmutableList.of(getClass().getName()))
+                .put(JcloudsLocation.WAIT_FOR_SSHABLE.getName(), false)
+                .put(JcloudsLocation.JCLOUDS_LOCATION_CUSTOMIZERS.getName(), 
ImmutableList.of(locationCustomizer))
+                .putAll(flags)
+                .put(JcloudsLocation.TEMPLATE_OPTIONS.getName(), 
templateOptions)
+                .build();
+        return (DockerJcloudsLocation) 
mgmt.getLocationRegistry().getLocationManaged("docker", allFlags);
+    }
+    
+    private JcloudsSshMachineLocation newDockerMachine(DockerJcloudsLocation 
loc, Map<?, ?> flags) throws Exception {
+        MachineLocation result = loc.obtain(flags);
+        machines.add(result);
+        return (JcloudsSshMachineLocation) result;
+    }
+
+    @Test(groups={"Live", "Live-sanity"})
+    public void testDefaultImageHasAutoGeneratedCredentials() throws Exception 
{
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        
+        assertMachineSshableSecureAndFromImage(machine, "cloudsoft/centos:7");
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testExplicitCredentialsNotOverwritten() throws Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
MutableMap.of(
+                JcloudsLocationConfig.LOGIN_USER, "myuser",
+                JcloudsLocationConfig.LOGIN_USER_PASSWORD, "mypassword"));
+        Image image = getOptionalImage(machine).get();
+        assertEquals(image.getDescription(), "cloudsoft/centos:7");
+        assertEquals(templateOptions.getLoginUser(), "myuser");
+        assertEquals(templateOptions.getLoginPassword(), "mypassword");
+        assertEquals(templateOptions.getLoginPassword(), "mypassword");
+        assertEnvNotContainsKey(templateOptions, "CLOUDSOFT_ROOT_PASSWORD");
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testExplicitImageIdNotOverwritten() throws Exception {
+        // TODO This id will likely change sometimes; once CCS-29 is done, 
then use an image name.
+        // Assumes we have executed:
+        //     docker run ubuntu /bin/echo 'Hello world'
+        // which will have downloaded the ubuntu image with the given id.
+        String imageId = 
"sha256:2fa927b5cdd31cdec0027ff4f45ef4343795c7a2d19a9af4f32425132a222330";
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
MutableMap.of(
+                JcloudsLocation.IMAGE_ID, imageId,
+                JcloudsLocation.TEMPLATE_OPTIONS, ImmutableMap.of(
+                        "entrypoint", ImmutableList.of("/bin/sleep", 
"1000"))));
+        Image image = getOptionalImage(machine).get();
+        assertEquals(image.getId(), imageId);
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testMatchingImageDescriptionHasAutoGeneratedCredentials() 
throws Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
+                JcloudsLocation.IMAGE_DESCRIPTION_REGEX.getName(), 
"cloudsoft/centos:7",
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        
+        assertTrue(machine.isSshable(), "machine="+machine);
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testMatchingOsFamilyCentosHasAutoGeneratedCredentials() throws 
Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
+                JcloudsLocation.OS_FAMILY.getName(), OsFamily.CENTOS,
+                JcloudsLocation.OS_VERSION_REGEX.getName(), "7.*",
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        
+        assertMachineSshableSecureAndFromImage(machine, "cloudsoft/centos:7");
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testMatchingOsFamilyUbuntu14HasAutoGeneratedCredentials() 
throws Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
+                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
+                JcloudsLocation.OS_VERSION_REGEX.getName(), "14.04.*",
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        
+        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:14.04");
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void testMatchingOsFamilyUbuntu16HasAutoGeneratedCredentials() 
throws Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of());
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
+                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
+                JcloudsLocation.OS_VERSION_REGEX.getName(), "16.04.*",
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        
+        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:16.04");
+    }
+    
+    @Test(groups={"Live", "Live-sanity"})
+    public void 
testMatchingOsFamilyConfiguredOnLocationHasAutoGeneratedCredentials() throws 
Exception {
+        loc = newDockerLocation(ImmutableMap.<String, Object>of(
+                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
+                JcloudsLocation.OS_VERSION_REGEX.getName(), "16.04.*",
+                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
+        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of());
+        
+        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:16.04");
+    }
+    
+    protected void 
assertMachineSshableSecureAndFromImage(JcloudsSshMachineLocation machine, 
String expectedImageDescription) throws Exception {
+        Image image = getOptionalImage(machine).get();
+        assertEquals(image.getDescription(), expectedImageDescription);
+        assertEquals(templateOptions.getLoginUser(), "root");
+        assertEnvContainsKeyValue(templateOptions, "CLOUDSOFT_ROOT_PASSWORD", 
templateOptions.getLoginPassword());
+        assertPasswordIsSecure(templateOptions.getLoginPassword());
+        
+        assertTrue(machine.isSshable(), "machine="+machine);
+    }
+    
+    protected void assertEnvNotContainsKey(DockerTemplateOptions 
templateOptions, String key) {
+        List<String> env = templateOptions.getEnv();
+        if (env == null) return;
+        for (String keyval : env) {
+            if (keyval.startsWith(key+"=")) {
+                fail("has key "+key+"; env="+env);
+            }
+        }
+    }
+    
+    protected void assertEnvContainsKeyValue(DockerTemplateOptions 
templateOptions, String key, String value) {
+        String keyval = key+"="+value;
+        List<String> env = templateOptions.getEnv();
+        if (env == null) {
+            fail("env is null; does not contain "+keyval);
+        }
+        if (!env.contains(keyval)) {
+            fail("env does not contain "+keyval+"; env="+env);
+        }
+    }
+    
+    protected void assertPasswordIsSecure(String val) {
+        if (!val.matches(".*[0-9].*")) {
+            fail("Password '"+val+"' does not contain a digit");
+        }
+        if (!val.matches(".*[A-Z].*")) {
+            fail("Password '"+val+"' does not contain an upper-case letter");
+        }
+        if (val.trim().length() < 7) {
+            fail("Password '"+val+"' is too short");
+        }
+        
+        LOG.debug("Password '"+val+"' passes basic security check");
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected Optional<Image> getOptionalImage(JcloudsSshMachineLocation 
machine) throws Exception {
+        Method method = 
machine.getClass().getDeclaredMethod("getOptionalImage");
+        method.setAccessible(true);
+        Optional<Image> result = (Optional<Image>) method.invoke(machine);
+        return checkNotNull(result, "null must not be returned by 
getOptionalImage, for %s", machine);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerLocationResolverTest.java
----------------------------------------------------------------------
diff --git 
a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerLocationResolverTest.java
 
b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerLocationResolverTest.java
new file mode 100644
index 0000000..d04ccf3
--- /dev/null
+++ 
b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/docker/DockerLocationResolverTest.java
@@ -0,0 +1,100 @@
+package io.cloudsoft.amp.containerservice.dockerlocation;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class DockerLocationResolverTest extends BrooklynMgmtUnitTestSupport {
+
+    @SuppressWarnings("unused")
+    private static final Logger log = 
LoggerFactory.getLogger(DockerLocationResolverTest.class);
+    
+    private BrooklynProperties brooklynProperties;
+
+    @BeforeMethod(alwaysRun = true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        brooklynProperties = mgmt.getBrooklynProperties();
+
+        brooklynProperties.put("brooklyn.location.docker.identity", 
"docker-id");
+        brooklynProperties.put("brooklyn.location.docker.credential", 
"docker-cred");
+    }
+
+    @Test
+    public void testGivesCorrectLocationType() {
+        LocationSpec<?> spec = getLocationSpec("docker");
+        assertEquals(spec.getType(), DockerJcloudsLocation.class);
+        
+        DockerJcloudsLocation loc = resolve("docker");
+        assertTrue(loc instanceof DockerJcloudsLocation, "loc="+loc);
+    }
+
+    @Test
+    public void testParametersInSpecString() {
+        DockerJcloudsLocation loc = 
resolve("docker(loginUser=myLoginUser,imageId=myImageId)");
+        assertEquals(loc.getConfig(DockerJcloudsLocation.LOGIN_USER), 
"myLoginUser");
+        assertEquals(loc.getConfig(DockerJcloudsLocation.IMAGE_ID), 
"myImageId");
+    }
+
+    @Test
+    public void testTakesDotSeparateProperty() {
+        brooklynProperties.put("brooklyn.location.docker.loginUser", 
"myLoginUser");
+        DockerJcloudsLocation loc = resolve("docker");
+        assertEquals(loc.getConfig(DockerJcloudsLocation.LOGIN_USER), 
"myLoginUser");
+    }
+
+    @Test
+    public void testPropertiesPrecedence() {
+        // prefer those in "spec" over everything else
+        brooklynProperties.put("brooklyn.location.named.mydocker", 
"docker:(loginUser=\"loginUser-inSpec\")");
+
+        brooklynProperties.put("brooklyn.location.named.mydocker.loginUser", 
"loginUser-inNamed");
+        brooklynProperties.put("brooklyn.location.docker.loginUser", 
"loginUser-inDocker");
+        brooklynProperties.put("brooklyn.location.jclouds.docker.loginUser", 
"loginUser-inJcloudsProviderSpecific");
+        brooklynProperties.put("brooklyn.location.jclouds.loginUser", 
"loginUser-inJcloudsGeneric");
+
+        // prefer those in "named" over everything else
+        
brooklynProperties.put("brooklyn.location.named.mydocker.privateKeyFile", 
"privateKeyFile-inNamed");
+        brooklynProperties.put("brooklyn.location.docker.privateKeyFile", 
"privateKeyFile-inDocker");
+        
brooklynProperties.put("brooklyn.location.jclouds.docker.privateKeyFile", 
"privateKeyFile-inJcloudsProviderSpecific");
+        brooklynProperties.put("brooklyn.location.jclouds.privateKeyFile", 
"privateKeyFile-inJcloudsGeneric");
+
+        // prefer those in docker-specific
+        brooklynProperties.put("brooklyn.location.docker.publicKeyFile", 
"publicKeyFile-inDocker");
+        
brooklynProperties.put("brooklyn.location.jclouds.docker.publicKeyFile", 
"publicKeyFile-inJcloudsProviderSpecific");
+        brooklynProperties.put("brooklyn.location.jclouds.publicKeyFile", 
"publicKeyFile-inJcloudsGeneric");
+
+        // prefer those in jclouds provider-specific
+        
brooklynProperties.put("brooklyn.location.jclouds.docker.privateKeyPassphrase", 
"privateKeyPassphrase-inJcloudsProviderSpecific");
+        
brooklynProperties.put("brooklyn.location.jclouds.privateKeyPassphrase", 
"privateKeyPassphrase-inJcloudsGeneric");
+
+        // accept those in jclouds generic
+        brooklynProperties.put("brooklyn.location.jclouds.privateKeyData", 
"privateKeyData-inJcloudsGeneric");
+
+        Map<String, Object> conf = 
resolve("named:mydocker").config().getBag().getAllConfig();
+
+        assertEquals(conf.get("loginUser"), "loginUser-inSpec");
+        assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed");
+        assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inDocker");
+        assertEquals(conf.get("privateKeyPassphrase"), 
"privateKeyPassphrase-inJcloudsProviderSpecific");
+        assertEquals(conf.get("privateKeyData"), 
"privateKeyData-inJcloudsGeneric");
+    }
+
+    private LocationSpec<?> getLocationSpec(String spec) {
+        return mgmt.getLocationRegistry().getLocationSpec(spec).get();
+    }
+
+    private DockerJcloudsLocation resolve(String spec) {
+        return (DockerJcloudsLocation) 
mgmt.getLocationRegistry().getLocationManaged(spec);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainer.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainer.java
 
b/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainer.java
deleted file mode 100644
index ef012c3..0000000
--- 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainer.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockercontainer;
-
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.BasicConfigInheritance;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.config.MapConfigKey;
-import org.apache.brooklyn.entity.software.base.SoftwareProcess;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
-
-/**
- * The DockerContainer type is for easily deploying any docker image from the
- * image repository set on the target swarm or docker-engine based location
- * <p>
- * Example YAML is shown below. Note the different types of the {@code env}
- * key in the location config and the {@code docker.container.environment}
- * key on the entity. The entity environment variables will override any
- * environment configured on the location. To specify environment variables
- * that will be set when executing SSH commands against the container you
- * should use the {@link SoftwareProcess#SHELL_ENVIRONMENT shell.env} key.
- * <p>
- * <pre>{@code location:
- *   docker:
- *     endpoint: "https://52.29.59.193:3376";
- *     identity: "~/.certs/cert.pem"
- *     credential: "~/.certs/key.pem"
- *     templateOptions:
- *       networkMode: "brooklyn"
- *     env:
- *       - "HTTP_CONFIG_ROOT=/var/httpd"
- *       - "USE_DEFAULTS=true"
- * services:
- *   - type: io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer
- *     brooklyn.config:
- *       docker.container.imageName: "apache/httpd:latest"
- *       docker.container.disableSsh: true
- *       docker.container.inboundPorts:
- *         - "8080-8081"
- *       docker.container.environment:
- *         ENABLE_JMX: false
- *         ENABLE_SHUTDOWN: false
- * }</pre>
- */
-@ImplementedBy(DockerContainerImpl.class)
-public interface DockerContainer extends SoftwareProcess {
-
-    ConfigKey<Boolean> DISABLE_SSH =
-            ConfigKeys.newBooleanConfigKey(
-                    "docker.container.disableSsh",
-                    "Skip checks such as ssh for when docker image doesn't 
allow ssh",
-                    Boolean.TRUE);
-
-    ConfigKey<String> IMAGE_NAME =
-            ConfigKeys.newStringConfigKey(
-                    "docker.container.imageName",
-                    "Image name to pull from docker hub");
-
-    @SuppressWarnings("serial")
-    ConfigKey<Iterable<String>> INBOUND_TCP_PORTS =
-            ConfigKeys.newConfigKey(
-                    new TypeToken<Iterable<String>>() {},
-                    "docker.container.inboundPorts",
-                    "List of ports, that the docker image opens, to be made 
public");
-
-    MapConfigKey<Object> CONTAINER_ENVIRONMENT = new 
MapConfigKey.Builder<Object>(Object.class, "docker.container.environment")
-            .description("Environment variables to set on container startup")
-            .defaultValue(ImmutableMap.<String, Object>of())
-            .typeInheritance(BasicConfigInheritance.DEEP_MERGE)
-            
.runtimeInheritance(BasicConfigInheritance.NOT_REINHERITED_ELSE_DEEP_MERGE)
-            .build();
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainerImpl.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainerImpl.java
 
b/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainerImpl.java
deleted file mode 100644
index 790985f..0000000
--- 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockercontainer/DockerContainerImpl.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockercontainer;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.EnricherSpec;
-import org.apache.brooklyn.core.entity.Attributes;
-import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
-import org.apache.brooklyn.core.location.PortRanges;
-import org.apache.brooklyn.core.network.OnPublicNetworkEnricher;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
-import org.apache.brooklyn.util.collections.MutableList;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableSet;
-
-public class DockerContainerImpl extends EmptySoftwareProcessImpl implements 
DockerContainer {
-
-   @Override
-   public void init() {
-      super.init();
-
-      String imageName = config().get(DockerContainer.IMAGE_NAME);
-      if (!Strings.isNullOrEmpty(imageName)) {
-         config().set(PROVISIONING_PROPERTIES.subKey("imageId"), imageName);
-      }
-
-      if (Boolean.TRUE.equals(config().get(DockerContainer.DISABLE_SSH))) {
-         config().set(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, 
true);
-         config().set(PROVISIONING_PROPERTIES.subKey("useJcloudsSshInit"), 
false);
-         config().set(PROVISIONING_PROPERTIES.subKey("waitForSshable"), false);
-         
config().set(PROVISIONING_PROPERTIES.subKey("pollForFirstReachableAddress"), 
false);
-         config().set(EmptySoftwareProcessImpl.USE_SSH_MONITORING, false);
-      }
-
-      ImmutableSet.Builder<AttributeSensor<Integer>> builder = 
ImmutableSet.builder();
-      List<String> portRanges = 
MutableList.copyOf(config().get(DockerContainer.INBOUND_TCP_PORTS));
-      for (String portRange : portRanges) {
-         Iterator<Integer> iterator = 
PortRanges.fromString(portRange).iterator();
-         while (iterator.hasNext()) {
-            Integer port = iterator.next();
-            AttributeSensor<Integer> element = 
Sensors.newIntegerSensor("docker.port." + port);
-            sensors().set(element, port);
-            builder.add(element);
-         }
-      }
-
-      
enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class).configure(OnPublicNetworkEnricher.SENSORS,
 builder.build()));
-   }
-
-   @Override
-   protected void disconnectSensors() {
-      if(isSshMonitoringEnabled()) {
-         disconnectServiceUpIsRunning();
-      }
-      super.disconnectSensors();
-   }
-
-   @Override
-   protected void connectSensors() {
-      super.connectSensors();
-      if (isSshMonitoringEnabled()) {
-         connectServiceUpIsRunning();
-      } else {
-         sensors().set(Attributes.SERVICE_UP, true);
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocation.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocation.java
 
b/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocation.java
deleted file mode 100644
index ecf3214..0000000
--- 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocation.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockerlocation;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.api.location.NoMachinesAvailableException;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.location.LocationConfigKeys;
-import org.apache.brooklyn.location.jclouds.JcloudsLocation;
-import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
-import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.apache.brooklyn.util.text.Strings;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.docker.compute.options.DockerTemplateOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Functions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-
-import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer;
-
-/**
- * For provisioning docker containers, using the jclouds-docker integration.
- * 
- * This adds special support for default Cloudsoft images. If the image 
description matches our 
- * cloudsoft regexes, then auto-generate a password and pass that in as 
- * {@code CLOUDSOFT_ROOT_PASSWORD} when launching the container. That will 
then be used as the 
- * {@link DockerTemplateOptions#getLoginPassword()}.
- * 
- * Also, if no image is specified then this will set the default to 
"cloudsoft/centos:7"
- * (see https://hub.docker.com/r/cloudsoft/centos/).
- */
-public class DockerJcloudsLocation extends JcloudsLocation {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(DockerJcloudsLocation.class);
-
-    public static final ConfigKey<Boolean> INJECT_LOGIN_CREDENTIAL = 
ConfigKeys.newBooleanConfigKey(
-            "injectLoginCredential", 
-            "Whether to inject login credentials (if null, will infer from 
image choice)", 
-            null);
-
-    public static final ConfigKey<String> DEFAULT_IMAGE_DESCRIPTION_REGEX = 
ConfigKeys.newStringConfigKey(
-            "defaultImageDescriptionRegex", 
-            "The default image description to use, if no other image 
preferences are supplied",
-            "cloudsoft/centos:7");
-
-    /**
-     * The regex for the image descriptions that support us injecting login 
credentials.
-     */
-    private static final List<String> 
IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS = ImmutableList.of(
-            "cloudsoft/centos.*",
-            "cloudsoft/ubuntu.*");
-
-    private static final List<ImageMetadata> DEFAULT_IMAGES = ImmutableList.of(
-            new ImageMetadata(OsFamily.CENTOS, "7", "cloudsoft/centos:7"),
-            new ImageMetadata(OsFamily.UBUNTU, "14.04", 
"cloudsoft/ubuntu:14.04"),
-            new ImageMetadata(OsFamily.UBUNTU, "16.04", 
"cloudsoft/ubuntu:16.04"));
-
-    private static class ImageMetadata {
-        private final OsFamily osFamily;
-        private final String osVersion;
-        private final String imageDescription;
-        
-        public ImageMetadata(OsFamily osFamily, String osVersion, String 
imageDescription) {
-            this.osFamily = checkNotNull(osFamily, "osFamily");
-            this.osVersion = checkNotNull(osVersion, "osVersion");
-            this.imageDescription = checkNotNull(imageDescription, 
"imageDescription");
-        }
-        
-        public boolean matches(@Nullable OsFamily osFamily, @Nullable String 
osVersionRegex) {
-            if (osFamily != null && osFamily != this.osFamily) return false;
-            if (osVersionRegex != null && !osVersion.matches(osVersionRegex)) 
return false;
-            return true;
-        }
-        
-        public String getImageDescription() {
-            return imageDescription;
-        }
-    }
-
-    @Override
-    protected MachineLocation obtainOnce(ConfigBag setup) throws 
NoMachinesAvailableException {
-        // Use the provider name that jclouds expects; rely on resolver to 
have validated this.
-        setup.configure(JcloudsLocation.CLOUD_PROVIDER, "docker");
-        
-        // Inject default image, if absent
-        String imageId = setup.get(JcloudsLocation.IMAGE_ID);
-        String imageNameRegex = setup.get(JcloudsLocation.IMAGE_NAME_REGEX);
-        String imageDescriptionRegex = 
setup.get(JcloudsLocation.IMAGE_DESCRIPTION_REGEX);
-        String defaultImageDescriptionRegex = 
setup.get(DEFAULT_IMAGE_DESCRIPTION_REGEX);
-        OsFamily osFamily = setup.get(OS_FAMILY);
-        String osVersionRegex = setup.get(OS_VERSION_REGEX);
-        
-        if (Strings.isBlank(imageId) && Strings.isBlank(imageNameRegex) && 
Strings.isBlank(imageDescriptionRegex)) {
-            if (osFamily != null || osVersionRegex != null) {
-                for (ImageMetadata imageMetadata : DEFAULT_IMAGES) {
-                    if (imageMetadata.matches(osFamily, osVersionRegex)) {
-                        String imageDescription = 
imageMetadata.getImageDescription();
-                        LOG.debug("Setting default image regex to {}, for 
obtain call in {}; removing osFamily={} and osVersionRegex={}", 
-                                new Object[] {imageDescription, this, 
osFamily, osVersionRegex});
-                        
setup.configure(JcloudsLocation.IMAGE_DESCRIPTION_REGEX, imageDescription);
-                        setup.configure(OS_FAMILY, null);
-                        setup.configure(OS_VERSION_REGEX, null);
-                        break;
-                    }
-                }
-            } else if (Strings.isNonBlank(defaultImageDescriptionRegex)) {
-                LOG.debug("Setting default image regex to {}, for obtain call 
in {}", defaultImageDescriptionRegex, this);
-                setup.configure(JcloudsLocation.IMAGE_DESCRIPTION_REGEX, 
defaultImageDescriptionRegex);
-            }
-        }
-        
-        return super.obtainOnce(setup);
-    }
-    
-    @Override
-    public Template buildTemplate(ComputeService computeService, ConfigBag 
config, Collection<JcloudsLocationCustomizer> customizers) {
-        String loginUser = config.get(JcloudsLocation.LOGIN_USER);
-        String loginPassword = config.get(JcloudsLocation.LOGIN_USER_PASSWORD);
-        String loginKeyFile = 
config.get(JcloudsLocation.LOGIN_USER_PRIVATE_KEY_FILE);
-        String loginKeyData = 
config.get(JcloudsLocation.LOGIN_USER_PRIVATE_KEY_DATA);
-
-        Template template = super.buildTemplate(computeService, config, 
customizers);
-        DockerTemplateOptions templateOptions = (DockerTemplateOptions) 
template.getOptions();
-        Image image = template.getImage();
-        List<String> env = MutableList.copyOf(templateOptions.getEnv());
-
-        // Inject login credentials, if required
-        Boolean injectLoginCredentials = config.get(INJECT_LOGIN_CREDENTIAL);
-        if (injectLoginCredentials == null) {
-            String imageDescription = image.getDescription();
-            for (String regex : 
IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS) {
-                if (imageDescription != null && 
imageDescription.matches(regex)) {
-                    injectLoginCredentials = true;
-                    break;
-                }
-            }
-        }
-        if (Strings.isBlank(loginUser) && Strings.isBlank(loginPassword) && 
Strings.isBlank(loginKeyFile) && Strings.isBlank(loginKeyData)) {
-            if (Boolean.TRUE.equals(injectLoginCredentials)) {
-                loginUser = "root";
-                loginPassword = Identifiers.makeRandomPassword(12);
-                templateOptions.overrideLoginUser(loginUser);
-                templateOptions.overrideLoginPassword(loginPassword);
-
-                env.add("CLOUDSOFT_ROOT_PASSWORD="+loginPassword);
-            }
-        }
-
-        Entity context = validateCallerContext(config);
-        Map<String,Object> containerEnv = 
MutableMap.copyOf(context.config().get(DockerContainer.CONTAINER_ENVIRONMENT));
-        for (Map.Entry<String,String> entry : 
Maps.transformValues(containerEnv, Functions.toStringFunction()).entrySet()) {
-            env.add(String.format("%s=%s", entry.getKey(), entry.getValue()));
-        }
-        templateOptions.env(env);
-
-        return template;
-    }
-
-
-    private Entity validateCallerContext(ConfigBag setup) {
-        // Lookup entity flags
-        Object callerContext = setup.get(LocationConfigKeys.CALLER_CONTEXT);
-        if (callerContext == null || !(callerContext instanceof Entity)) {
-            throw new IllegalStateException("Invalid caller context: " + 
callerContext);
-        }
-        return (Entity) callerContext;
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolver.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolver.java
 
b/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolver.java
deleted file mode 100644
index d6c8c99..0000000
--- 
a/docker-location/src/main/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolver.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockerlocation;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationResolver;
-import org.apache.brooklyn.core.location.AbstractLocationResolver;
-import org.apache.brooklyn.core.location.LocationConfigUtils;
-import 
org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties;
-import 
org.apache.brooklyn.location.jclouds.JcloudsPropertiesFromBrooklynProperties;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Locations starting with the given prefix (@code "docker") will use this 
resolver, to instantiate
- * a {@link DockerJcloudsLocation}.
- * 
- * We ensure that config will be picked up from brooklyn.properties using the 
appropriate precedence:
- * <ol>
- *   <li>named location config
- *   <li>Prefix {@code brooklyn.location.docker.}
- *   <li>Prefix {@code brooklyn.jclouds.docker.}
- *   <li>Prefix {@code brooklyn.jclouds.}
- * </ol>
- */
-public class DockerLocationResolver extends AbstractLocationResolver 
implements LocationResolver {
-
-    public static final Logger log = 
LoggerFactory.getLogger(DockerLocationResolver.class);
-    
-    public static final String PREFIX = "docker";
-
-    @Override
-    public boolean isEnabled() {
-        return LocationConfigUtils.isResolverPrefixEnabled(managementContext, 
getPrefix());
-    }
-    
-    @Override
-    public String getPrefix() {
-        return PREFIX;
-    }
-    
-    @Override
-    protected Class<? extends Location> getLocationType() {
-        return DockerJcloudsLocation.class;
-    }
-
-    @Override
-    protected SpecParser getSpecParser() {
-        return new 
AbstractLocationResolver.SpecParser(getPrefix()).setExampleUsage("\"docker\"");
-    }
-
-    @Override
-    protected Map<String, Object> getFilteredLocationProperties(String 
provider, String namedLocation, Map<String, ?> prioritisedProperties, 
Map<String, ?> globalProperties) {
-        Map<String, Object> dockerConf = new 
LocationPropertiesFromBrooklynProperties().getLocationProperties(getPrefix(), 
namedLocation, globalProperties);
-        
-        Object providerInConf = dockerConf.get("provider");
-        if (providerInConf != null && !provider.equals(providerInConf)) {
-            throw new IllegalArgumentException(provider+" location configured 
with provider '"+providerInConf+"', but must be blank or '"+provider+"'");
-        }
-
-        String providerOrApi = "docker";
-        String regionName = (String) prioritisedProperties.get("region");
-        Map<String, Object> jcloudsConf = new 
JcloudsPropertiesFromBrooklynProperties().getJcloudsProperties(providerOrApi, 
regionName, namedLocation, globalProperties);
-        return MutableMap.<String, Object>builder()
-                .putAll(jcloudsConf)
-                .putAll(dockerConf)
-                .put("provider", providerOrApi)
-                .build();
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocationLiveTest.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocationLiveTest.java
 
b/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocationLiveTest.java
deleted file mode 100644
index eb64173..0000000
--- 
a/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerJcloudsLocationLiveTest.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockerlocation;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
-import org.apache.brooklyn.location.jclouds.BasicJcloudsLocationCustomizer;
-import org.apache.brooklyn.location.jclouds.JcloudsLocation;
-import org.apache.brooklyn.location.jclouds.JcloudsLocationConfig;
-import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
-import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.os.Os;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.docker.compute.options.DockerTemplateOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-/**
- * TODO For these tests to pass, they need on the classpath the patch file(s) 
from AMP.
- * 
- * Assumes that a pre-existing swarm endpoint is available. See system 
properties and the defaults
- * below.
- */
-public class DockerJcloudsLocationLiveTest extends BrooklynAppLiveTestSupport {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(DockerJcloudsLocationLiveTest.class);
-    
-    private static final String SWARM_ENDPOINT = 
System.getProperty("test.amp.docker.swarmEndpoint", 
"https://10.104.0.162:3376/";);
-    private static final String IDENTITY_FILE_PATH = 
System.getProperty("test.amp.docker.identity", 
Os.tidyPath("~/.docker/.certs/cert.pem"));
-    private static final String CREDENTIAL_FILE_PATH = 
System.getProperty("test.amp.docker.credential", 
Os.tidyPath("~/.docker/.certs/key.pem"));
-    private static final String SWARM_NETWORK_NAME = 
System.getProperty("test.amp.docker.networkName", Os.tidyPath("brooklyn"));
-    
-    protected DockerJcloudsLocation loc;
-    protected List<MachineLocation> machines;
-    protected DockerTemplateOptions templateOptions;
-    
-    @BeforeMethod(alwaysRun=true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        machines = Lists.newCopyOnWriteArrayList();
-    }
-    
-    @AfterMethod(alwaysRun=true)
-    @Override
-    public void tearDown() throws Exception {
-        for (MachineLocation machine : machines) {
-            try {
-                loc.release(machine);
-            } catch (Exception e) {
-                LOG.error("Error releasing machine "+machine+" in location 
"+loc, e);
-            }
-        }
-        super.tearDown();
-    }
-    
-    protected DockerJcloudsLocation newDockerLocation(Map<String, ?> flags) 
throws Exception {
-        JcloudsLocationCustomizer locationCustomizer = new 
BasicJcloudsLocationCustomizer() {
-            @Override
-            public void customize(JcloudsLocation location, ComputeService 
computeService, TemplateOptions templateOptions) {
-                DockerJcloudsLocationLiveTest.this.templateOptions = 
(DockerTemplateOptions) templateOptions;
-            }
-        };
-        Map<String, ?> templateOptionsOverrides = (Map<String, ?>) 
flags.get(JcloudsLocation.TEMPLATE_OPTIONS.getName());
-        Map<String,?> templateOptions = MutableMap.<String, Object>builder()
-                .put("networkMode", SWARM_NETWORK_NAME)
-                .putAll(templateOptionsOverrides != null ? 
templateOptionsOverrides : ImmutableMap.<String, Object>of())
-                .build();
-        Map<String,?> allFlags = MutableMap.<String,Object>builder()
-                .put("identity", IDENTITY_FILE_PATH)
-                .put("credential", CREDENTIAL_FILE_PATH)
-                .put("endpoint", SWARM_ENDPOINT)
-                .put("tags", ImmutableList.of(getClass().getName()))
-                .put(JcloudsLocation.WAIT_FOR_SSHABLE.getName(), false)
-                .put(JcloudsLocation.JCLOUDS_LOCATION_CUSTOMIZERS.getName(), 
ImmutableList.of(locationCustomizer))
-                .putAll(flags)
-                .put(JcloudsLocation.TEMPLATE_OPTIONS.getName(), 
templateOptions)
-                .build();
-        return (DockerJcloudsLocation) 
mgmt.getLocationRegistry().getLocationManaged("docker", allFlags);
-    }
-    
-    private JcloudsSshMachineLocation newDockerMachine(DockerJcloudsLocation 
loc, Map<?, ?> flags) throws Exception {
-        MachineLocation result = loc.obtain(flags);
-        machines.add(result);
-        return (JcloudsSshMachineLocation) result;
-    }
-
-    @Test(groups={"Live", "Live-sanity"})
-    public void testDefaultImageHasAutoGeneratedCredentials() throws Exception 
{
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        
-        assertMachineSshableSecureAndFromImage(machine, "cloudsoft/centos:7");
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testExplicitCredentialsNotOverwritten() throws Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
MutableMap.of(
-                JcloudsLocationConfig.LOGIN_USER, "myuser",
-                JcloudsLocationConfig.LOGIN_USER_PASSWORD, "mypassword"));
-        Image image = getOptionalImage(machine).get();
-        assertEquals(image.getDescription(), "cloudsoft/centos:7");
-        assertEquals(templateOptions.getLoginUser(), "myuser");
-        assertEquals(templateOptions.getLoginPassword(), "mypassword");
-        assertEquals(templateOptions.getLoginPassword(), "mypassword");
-        assertEnvNotContainsKey(templateOptions, "CLOUDSOFT_ROOT_PASSWORD");
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testExplicitImageIdNotOverwritten() throws Exception {
-        // TODO This id will likely change sometimes; once CCS-29 is done, 
then use an image name.
-        // Assumes we have executed:
-        //     docker run ubuntu /bin/echo 'Hello world'
-        // which will have downloaded the ubuntu image with the given id.
-        String imageId = 
"sha256:2fa927b5cdd31cdec0027ff4f45ef4343795c7a2d19a9af4f32425132a222330";
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
MutableMap.of(
-                JcloudsLocation.IMAGE_ID, imageId,
-                JcloudsLocation.TEMPLATE_OPTIONS, ImmutableMap.of(
-                        "entrypoint", ImmutableList.of("/bin/sleep", 
"1000"))));
-        Image image = getOptionalImage(machine).get();
-        assertEquals(image.getId(), imageId);
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testMatchingImageDescriptionHasAutoGeneratedCredentials() 
throws Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
-                JcloudsLocation.IMAGE_DESCRIPTION_REGEX.getName(), 
"cloudsoft/centos:7",
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        
-        assertTrue(machine.isSshable(), "machine="+machine);
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testMatchingOsFamilyCentosHasAutoGeneratedCredentials() throws 
Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
-                JcloudsLocation.OS_FAMILY.getName(), OsFamily.CENTOS,
-                JcloudsLocation.OS_VERSION_REGEX.getName(), "7.*",
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        
-        assertMachineSshableSecureAndFromImage(machine, "cloudsoft/centos:7");
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testMatchingOsFamilyUbuntu14HasAutoGeneratedCredentials() 
throws Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
-                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
-                JcloudsLocation.OS_VERSION_REGEX.getName(), "14.04.*",
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        
-        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:14.04");
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void testMatchingOsFamilyUbuntu16HasAutoGeneratedCredentials() 
throws Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of());
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of(
-                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
-                JcloudsLocation.OS_VERSION_REGEX.getName(), "16.04.*",
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        
-        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:16.04");
-    }
-    
-    @Test(groups={"Live", "Live-sanity"})
-    public void 
testMatchingOsFamilyConfiguredOnLocationHasAutoGeneratedCredentials() throws 
Exception {
-        loc = newDockerLocation(ImmutableMap.<String, Object>of(
-                JcloudsLocation.OS_FAMILY.getName(), OsFamily.UBUNTU,
-                JcloudsLocation.OS_VERSION_REGEX.getName(), "16.04.*",
-                JcloudsLocation.WAIT_FOR_SSHABLE.getName(), "1m"));
-        JcloudsSshMachineLocation machine = newDockerMachine(loc, 
ImmutableMap.<String, Object>of());
-        
-        assertMachineSshableSecureAndFromImage(machine, 
"cloudsoft/ubuntu:16.04");
-    }
-    
-    protected void 
assertMachineSshableSecureAndFromImage(JcloudsSshMachineLocation machine, 
String expectedImageDescription) throws Exception {
-        Image image = getOptionalImage(machine).get();
-        assertEquals(image.getDescription(), expectedImageDescription);
-        assertEquals(templateOptions.getLoginUser(), "root");
-        assertEnvContainsKeyValue(templateOptions, "CLOUDSOFT_ROOT_PASSWORD", 
templateOptions.getLoginPassword());
-        assertPasswordIsSecure(templateOptions.getLoginPassword());
-        
-        assertTrue(machine.isSshable(), "machine="+machine);
-    }
-    
-    protected void assertEnvNotContainsKey(DockerTemplateOptions 
templateOptions, String key) {
-        List<String> env = templateOptions.getEnv();
-        if (env == null) return;
-        for (String keyval : env) {
-            if (keyval.startsWith(key+"=")) {
-                fail("has key "+key+"; env="+env);
-            }
-        }
-    }
-    
-    protected void assertEnvContainsKeyValue(DockerTemplateOptions 
templateOptions, String key, String value) {
-        String keyval = key+"="+value;
-        List<String> env = templateOptions.getEnv();
-        if (env == null) {
-            fail("env is null; does not contain "+keyval);
-        }
-        if (!env.contains(keyval)) {
-            fail("env does not contain "+keyval+"; env="+env);
-        }
-    }
-    
-    protected void assertPasswordIsSecure(String val) {
-        if (!val.matches(".*[0-9].*")) {
-            fail("Password '"+val+"' does not contain a digit");
-        }
-        if (!val.matches(".*[A-Z].*")) {
-            fail("Password '"+val+"' does not contain an upper-case letter");
-        }
-        if (val.trim().length() < 7) {
-            fail("Password '"+val+"' is too short");
-        }
-        
-        LOG.debug("Password '"+val+"' passes basic security check");
-    }
-    
-    @SuppressWarnings("unchecked")
-    protected Optional<Image> getOptionalImage(JcloudsSshMachineLocation 
machine) throws Exception {
-        Method method = 
machine.getClass().getDeclaredMethod("getOptionalImage");
-        method.setAccessible(true);
-        Optional<Image> result = (Optional<Image>) method.invoke(machine);
-        return checkNotNull(result, "null must not be returned by 
getOptionalImage, for %s", machine);
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e890c003/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolverTest.java
----------------------------------------------------------------------
diff --git 
a/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolverTest.java
 
b/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolverTest.java
deleted file mode 100644
index d04ccf3..0000000
--- 
a/docker-location/src/test/java/io/cloudsoft/amp/containerservice/dockerlocation/DockerLocationResolverTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package io.cloudsoft.amp.containerservice.dockerlocation;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.core.internal.BrooklynProperties;
-import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class DockerLocationResolverTest extends BrooklynMgmtUnitTestSupport {
-
-    @SuppressWarnings("unused")
-    private static final Logger log = 
LoggerFactory.getLogger(DockerLocationResolverTest.class);
-    
-    private BrooklynProperties brooklynProperties;
-
-    @BeforeMethod(alwaysRun = true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        brooklynProperties = mgmt.getBrooklynProperties();
-
-        brooklynProperties.put("brooklyn.location.docker.identity", 
"docker-id");
-        brooklynProperties.put("brooklyn.location.docker.credential", 
"docker-cred");
-    }
-
-    @Test
-    public void testGivesCorrectLocationType() {
-        LocationSpec<?> spec = getLocationSpec("docker");
-        assertEquals(spec.getType(), DockerJcloudsLocation.class);
-        
-        DockerJcloudsLocation loc = resolve("docker");
-        assertTrue(loc instanceof DockerJcloudsLocation, "loc="+loc);
-    }
-
-    @Test
-    public void testParametersInSpecString() {
-        DockerJcloudsLocation loc = 
resolve("docker(loginUser=myLoginUser,imageId=myImageId)");
-        assertEquals(loc.getConfig(DockerJcloudsLocation.LOGIN_USER), 
"myLoginUser");
-        assertEquals(loc.getConfig(DockerJcloudsLocation.IMAGE_ID), 
"myImageId");
-    }
-
-    @Test
-    public void testTakesDotSeparateProperty() {
-        brooklynProperties.put("brooklyn.location.docker.loginUser", 
"myLoginUser");
-        DockerJcloudsLocation loc = resolve("docker");
-        assertEquals(loc.getConfig(DockerJcloudsLocation.LOGIN_USER), 
"myLoginUser");
-    }
-
-    @Test
-    public void testPropertiesPrecedence() {
-        // prefer those in "spec" over everything else
-        brooklynProperties.put("brooklyn.location.named.mydocker", 
"docker:(loginUser=\"loginUser-inSpec\")");
-
-        brooklynProperties.put("brooklyn.location.named.mydocker.loginUser", 
"loginUser-inNamed");
-        brooklynProperties.put("brooklyn.location.docker.loginUser", 
"loginUser-inDocker");
-        brooklynProperties.put("brooklyn.location.jclouds.docker.loginUser", 
"loginUser-inJcloudsProviderSpecific");
-        brooklynProperties.put("brooklyn.location.jclouds.loginUser", 
"loginUser-inJcloudsGeneric");
-
-        // prefer those in "named" over everything else
-        
brooklynProperties.put("brooklyn.location.named.mydocker.privateKeyFile", 
"privateKeyFile-inNamed");
-        brooklynProperties.put("brooklyn.location.docker.privateKeyFile", 
"privateKeyFile-inDocker");
-        
brooklynProperties.put("brooklyn.location.jclouds.docker.privateKeyFile", 
"privateKeyFile-inJcloudsProviderSpecific");
-        brooklynProperties.put("brooklyn.location.jclouds.privateKeyFile", 
"privateKeyFile-inJcloudsGeneric");
-
-        // prefer those in docker-specific
-        brooklynProperties.put("brooklyn.location.docker.publicKeyFile", 
"publicKeyFile-inDocker");
-        
brooklynProperties.put("brooklyn.location.jclouds.docker.publicKeyFile", 
"publicKeyFile-inJcloudsProviderSpecific");
-        brooklynProperties.put("brooklyn.location.jclouds.publicKeyFile", 
"publicKeyFile-inJcloudsGeneric");
-
-        // prefer those in jclouds provider-specific
-        
brooklynProperties.put("brooklyn.location.jclouds.docker.privateKeyPassphrase", 
"privateKeyPassphrase-inJcloudsProviderSpecific");
-        
brooklynProperties.put("brooklyn.location.jclouds.privateKeyPassphrase", 
"privateKeyPassphrase-inJcloudsGeneric");
-
-        // accept those in jclouds generic
-        brooklynProperties.put("brooklyn.location.jclouds.privateKeyData", 
"privateKeyData-inJcloudsGeneric");
-
-        Map<String, Object> conf = 
resolve("named:mydocker").config().getBag().getAllConfig();
-
-        assertEquals(conf.get("loginUser"), "loginUser-inSpec");
-        assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed");
-        assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inDocker");
-        assertEquals(conf.get("privateKeyPassphrase"), 
"privateKeyPassphrase-inJcloudsProviderSpecific");
-        assertEquals(conf.get("privateKeyData"), 
"privateKeyData-inJcloudsGeneric");
-    }
-
-    private LocationSpec<?> getLocationSpec(String spec) {
-        return mgmt.getLocationRegistry().getLocationSpec(spec).get();
-    }
-
-    private DockerJcloudsLocation resolve(String spec) {
-        return (DockerJcloudsLocation) 
mgmt.getLocationRegistry().getLocationManaged(spec);
-    }
-}

Reply via email to