From 4a9eca5cfe5162faf4b626a3848b5da1727f4a9f Mon Sep 17 00:00:00 2001 From: Andrew Kennedy Date: Wed, 8 Apr 2015 20:38:17 +0100 Subject: [PATCH 1/5] Added Docker service type resolver --- .../DockerServiceTypeResolver.java | 81 +++++++++++++++++++ ...n.spi.creation.service.ServiceTypeResolver | 1 + .../files/blueprints/docker-mysql.yaml | 19 ++--- .../files/blueprints/docker-redis.yaml | 15 ++-- 4 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java create mode 100644 docker/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver diff --git a/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java b/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java new file mode 100644 index 00000000..142da5b2 --- /dev/null +++ b/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package brooklyn.entity.container.docker.application; + +import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; +import io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver; +import io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver; +import io.brooklyn.camp.spi.PlatformComponentTemplate; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.catalog.CatalogItem; +import brooklyn.entity.Entity; +import brooklyn.entity.container.DockerAttributes; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.util.text.Strings; + +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; + +/** + * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code docker:} + * to Brooklyn {@link EntitySpec} instances. + */ +public class DockerServiceTypeResolver extends BrooklynServiceTypeResolver { + + private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class); + + public static final String PREFIX = "docker"; + + @Override + public String getTypePrefix() { return PREFIX; } + + @Override + public String getBrooklynType(String serviceType) { + return VanillaDockerApplication.class.getName(); + } + + // docker: items are not in catalog + @Override + public CatalogItem> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) { + return null; + } + + @Override + public void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec spec) { + String dockerServiceType = Strings.removeFromStart(resolver.getDeclaredType(), PREFIX + ":"); + List parts = Splitter.on(":").splitToList(dockerServiceType); + if (parts.isEmpty() || parts.size() > 2) { + throw new IllegalArgumentException("Docker serviceType cannot be parsed: " + dockerServiceType); + } + String imageName = Iterables.get(parts, 0); + String imageTag = Iterables.get(parts, 1, "latest"); + log.debug("Creating Docker service entity with image {} and tag {}", imageName, imageTag); + spec.configure(DockerAttributes.DOCKER_IMAGE_NAME, imageName); + if (parts.size() == 2) { + spec.configure(DockerAttributes.DOCKER_IMAGE_TAG, imageTag); + } + super.decorateSpec(resolver, spec); + } + +} diff --git a/docker/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver b/docker/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver new file mode 100644 index 00000000..6471d332 --- /dev/null +++ b/docker/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver @@ -0,0 +1 @@ +brooklyn.entity.container.docker.application.DockerServiceTypeResolver \ No newline at end of file diff --git a/examples/src/main/assembly/files/blueprints/docker-mysql.yaml b/examples/src/main/assembly/files/blueprints/docker-mysql.yaml index f84648e4..1b870d5c 100644 --- a/examples/src/main/assembly/files/blueprints/docker-mysql.yaml +++ b/examples/src/main/assembly/files/blueprints/docker-mysql.yaml @@ -19,15 +19,10 @@ locations: - my-docker-cloud services: -- type: brooklyn.entity.container.docker.application.VanillaDockerApplication - id: mysql - name: "MySQL" - brooklyn.config: - docker.image.name: mysql - docker.image.tag: 5.7 - docker.container.openPorts: - - 3306 - docker.container.directPorts: - - 3306 - docker.container.environment: - MYSQL_ROOT_PASSWORD: "s3cr3t" \ No newline at end of file +- type: docker:mysql:5.7 + openPorts: + - 3306 + directPorts: + - 3306 + env: + MYSQL_ROOT_PASSWORD: "s3cr3t" \ No newline at end of file diff --git a/examples/src/main/assembly/files/blueprints/docker-redis.yaml b/examples/src/main/assembly/files/blueprints/docker-redis.yaml index c9f5fe50..74ee361a 100644 --- a/examples/src/main/assembly/files/blueprints/docker-redis.yaml +++ b/examples/src/main/assembly/files/blueprints/docker-redis.yaml @@ -19,13 +19,8 @@ locations: - my-docker-cloud services: -- type: brooklyn.entity.container.docker.application.VanillaDockerApplication - id: redis - name: "Redis" - brooklyn.config: - docker.image.name: redis - docker.image.tag: 2.8.19 - docker.container.openPorts: - - 6379 - docker.container.directPorts: - - 6379 +- type: docker:redis:2.8.19 + openPorts: + - 6379 + directPorts: + - 6379 From e6c6e22844e95b15fdfe978116484682ec11639c Mon Sep 17 00:00:00 2001 From: Andrew Kennedy Date: Wed, 8 Apr 2015 21:20:48 +0100 Subject: [PATCH 2/5] Repository config being used incorrectly for image names --- .../entity/container/DockerUtils.java | 4 +-- .../entity/container/docker/DockerHost.java | 6 ----- .../container/docker/DockerHostDriver.java | 2 -- .../container/docker/DockerHostImpl.java | 16 ++---------- .../container/docker/DockerHostSshDriver.java | 16 +++--------- .../docker/DockerInfrastructureImpl.java | 1 - .../docker/DockerContainerLocation.java | 9 ++----- .../location/docker/DockerHostLocation.java | 26 +++---------------- .../options/DockerTemplateOptions.java | 19 +++++++------- .../files/blueprints/docker-freehub-demo.yaml | 26 +++++++++++++++++++ 10 files changed, 50 insertions(+), 75 deletions(-) create mode 100644 examples/src/main/assembly/files/blueprints/docker-freehub-demo.yaml diff --git a/docker/src/main/java/brooklyn/entity/container/DockerUtils.java b/docker/src/main/java/brooklyn/entity/container/DockerUtils.java index 97792bbd..549f96e9 100644 --- a/docker/src/main/java/brooklyn/entity/container/DockerUtils.java +++ b/docker/src/main/java/brooklyn/entity/container/DockerUtils.java @@ -151,11 +151,11 @@ public static String checkId(String input) { } } - public static String imageName(Entity entity, String dockerfile, String repository) { + public static String imageName(Entity entity, String dockerfile) { String simpleName = entity.getEntityType().getSimpleName(); String version = entity.config().get(SoftwareProcess.SUGGESTED_VERSION); - String label = Joiner.on(":").skipNulls().join(simpleName, version, dockerfile, repository); + String label = Joiner.on(":").skipNulls().join(simpleName, version, dockerfile); return Identifiers.makeIdFromHash(Hashing.md5().hashString(label, Charsets.UTF_8).asLong()).toLowerCase(Locale.ENGLISH); } diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerHost.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerHost.java index c0e887f6..fa7a7273 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerHost.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerHost.java @@ -93,10 +93,6 @@ public interface DockerHost extends MachineEntity, Resizable, HasShortName, Loca ConfigKey DOCKER_HOST_NAME_FORMAT = ConfigKeys.newStringConfigKey("docker.host.nameFormat", "Format for generating Docker host names", DockerUtils.DEFAULT_DOCKER_HOST_NAME_FORMAT); - @SetFromFlag("repository") - AttributeSensorAndConfigKey DOCKER_REPOSITORY = ConfigKeys.newStringSensorAndConfigKey("docker.repository", - "The name of the Docker repository for images"); - ConfigKey EPEL_RELEASE = ConfigKeys.newStringConfigKey("docker.host.epel.release", "EPEL release for yum based OS", "6-8"); @@ -136,8 +132,6 @@ public interface DockerHost extends MachineEntity, Resizable, HasShortName, Loca AttributeSensor DOCKER_HOST_SUBNET_TIER = Sensors.newSensor(SubnetTier.class, "docker.subnetTier", "The SubnetTier for Docker port mapping"); - String getRepository(); - String getPassword(); Integer getDockerPort(); diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostDriver.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostDriver.java index 5085d3e2..c7d85293 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostDriver.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostDriver.java @@ -24,8 +24,6 @@ public interface DockerHostDriver extends SoftwareProcessDriver { Integer getDockerPort(); - String getRepository(); - /** * Build a Docker image from the given Dockerfile. *

diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostImpl.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostImpl.java index 1e02e8df..e3669938 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostImpl.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostImpl.java @@ -119,12 +119,6 @@ public void init() { String dockerHostName = String.format(getConfig(DockerHost.DOCKER_HOST_NAME_FORMAT), getId(), counter.incrementAndGet()); setDisplayName(dockerHostName); setAttribute(DOCKER_HOST_NAME, dockerHostName); - String repository = getConfig(DOCKER_REPOSITORY); - if (Strings.isBlank(repository)) { - repository = getId(); - } - repository = DockerUtils.allowed(repository); - setAttribute(DOCKER_REPOSITORY, repository); // Set a password for this host's containers String password = config().get(DOCKER_PASSWORD); @@ -322,16 +316,11 @@ public String getPassword() { return config().get(DOCKER_PASSWORD); } - @Override - public String getRepository() { - return getAttribute(DOCKER_REPOSITORY); - } - /** {@inheritDoc} */ @Override public String createSshableImage(String dockerFile, String name) { String imageId = getDriver().buildImage(dockerFile, name); - LOG.debug("Successfully created image {} ({}/{})", new Object[] { imageId, getRepository(), name }); + LOG.debug("Successfully created image {} ({})", new Object[] { imageId, name }); return imageId; } @@ -488,7 +477,6 @@ protected void preStart() { .put("machine", found.get()) .put("jcloudsLocation", jcloudsLocation) .put("portForwarder", portForwarder) - .put("repository", getRepository()) .build(); createLocation(flags); } @@ -508,7 +496,7 @@ public void postStart() { if (Strings.isBlank(imageId)) { String dockerfileUrl = config().get(DockerInfrastructure.DOCKERFILE_URL); - String imageName = DockerUtils.imageName(this, dockerfileUrl, getRepository()); + String imageName = DockerUtils.imageName(this, dockerfileUrl); imageId = createSshableImage(dockerfileUrl, imageName); setAttribute(DOCKER_IMAGE_NAME, imageName); } diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostSshDriver.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostSshDriver.java index 8c5f7884..abc15f89 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerHostSshDriver.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerHostSshDriver.java @@ -107,11 +107,6 @@ public Integer getDockerPort() { return getEntity().getAttribute(DockerHost.DOCKER_SSL_PORT); } - @Override - public String getRepository() { - return getEntity().getAttribute(DockerHost.DOCKER_REPOSITORY); - } - /** {@inheritDoc} */ @Override public String buildImage(String dockerFile, String name) { @@ -149,7 +144,7 @@ public String layerSshableImageOn(String name, String tag) { checkNotNull(name, "name"); checkNotNull(tag, "tag"); copyTemplate(DockerUtils.SSHD_DOCKERFILE, Os.mergePaths(name, "Sshd" + DockerUtils.DOCKERFILE), - true, ImmutableMap.of("fullyQualifiedImageName", Os.mergePaths(name) + ":" + tag)); + true, ImmutableMap.of("fullyQualifiedImageName", name + ":" + tag)); String sshdImageId = buildDockerfile("Sshd" + DockerUtils.DOCKERFILE, name); log.info("Created SSH-based image from {} with ID {}", name, sshdImageId); @@ -157,8 +152,7 @@ public String layerSshableImageOn(String name, String tag) { } private Map getExtraTemplateSubstitutions(String imageName) { - Map templateSubstitutions = MutableMap.of( - "fullyQualifiedImageName", Os.mergePaths(getRepository(), imageName)); + Map templateSubstitutions = MutableMap.of("fullyQualifiedImageName", imageName); DockerHost host = (DockerHost) getEntity(); templateSubstitutions.putAll(host.getInfrastructure().config().get(DockerInfrastructure.DOCKERFILE_SUBSTITUTIONS)); return templateSubstitutions; @@ -166,8 +160,7 @@ private Map getExtraTemplateSubstitutions(String imageName) { private String buildDockerfileDirectory(String name) { String build = format("build --rm -t %s %s", - Os.mergePaths(getRepository(), name), - Os.mergePaths(getRunDir(), name)); + name, Os.mergePaths(getRunDir(), name)); String stdout = ((DockerHost) getEntity()).runDockerCommandTimeout(build, Duration.minutes(20)); String prefix = Strings.getFirstWordAfter(stdout, "Successfully built"); @@ -176,8 +169,7 @@ private String buildDockerfileDirectory(String name) { private String buildDockerfile(String dockerfile, String name) { String build = format("build --rm -t %s - < %s", - Os.mergePaths(getRepository(), name), - Os.mergePaths(getRunDir(), name, dockerfile)); + name, Os.mergePaths(getRunDir(), name, dockerfile)); String stdout = ((DockerHost) getEntity()).runDockerCommandTimeout(build, Duration.minutes(20)); String prefix = Strings.getFirstWordAfter(stdout, "Successfully built"); diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerInfrastructureImpl.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerInfrastructureImpl.java index 4d095d85..50933c13 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerInfrastructureImpl.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerInfrastructureImpl.java @@ -48,7 +48,6 @@ import brooklyn.entity.group.DynamicMultiGroup; import brooklyn.entity.machine.MachineAttributes; import brooklyn.entity.proxying.EntitySpec; -import brooklyn.entity.trait.Resizable; import brooklyn.entity.trait.Startable; import brooklyn.location.Location; import brooklyn.location.LocationDefinition; diff --git a/docker/src/main/java/brooklyn/location/docker/DockerContainerLocation.java b/docker/src/main/java/brooklyn/location/docker/DockerContainerLocation.java index 537ce7fe..50e6ebc6 100644 --- a/docker/src/main/java/brooklyn/location/docker/DockerContainerLocation.java +++ b/docker/src/main/java/brooklyn/location/docker/DockerContainerLocation.java @@ -47,7 +47,6 @@ import brooklyn.util.flags.SetFromFlag; import brooklyn.util.net.Cidr; import brooklyn.util.net.Protocol; -import brooklyn.util.os.Os; import brooklyn.util.ssh.IptablesCommands; import brooklyn.util.ssh.IptablesCommands.Chain; import brooklyn.util.ssh.IptablesCommands.Policy; @@ -95,10 +94,6 @@ public JcloudsSshMachineLocation getMachine() { return machine; } - public String getRepository() { - return dockerContainer.getDockerHost().getRepository(); - } - /* * Delegate port operations to machine. Note that firewall configuration is * fixed after initial provisioning, so updates use iptables to open ports. @@ -202,7 +197,7 @@ private void parseDockerCallback(String commandString) { String containerId = getOwner().getContainerId(); String imageName = getOwner().getAttribute(DockerContainer.IMAGE_NAME); String output = getOwner().getDockerHost().runDockerCommandTimeout( - format("commit %s %s", containerId, Os.mergePaths(getRepository(), imageName)), + format("commit %s %s", containerId, imageName), Duration.minutes(20)); String imageId = DockerUtils.checkId(output); ((EntityLocal) getOwner().getRunningEntity()).setAttribute(DockerContainer.IMAGE_ID, imageId); @@ -210,7 +205,7 @@ private void parseDockerCallback(String commandString) { getOwner().getDockerHost().getDynamicLocation().markImage(imageName); } else if (DockerCallbacks.PUSH.equalsIgnoreCase(command)) { String imageName = getOwner().getAttribute(DockerContainer.IMAGE_NAME); - getOwner().getDockerHost().runDockerCommand(format("push %s", Os.mergePaths(getRepository(), imageName))); + getOwner().getDockerHost().runDockerCommand(format("push %s", imageName)); } else if (DockerCallbacks.SUBNET_ADDRESS.equalsIgnoreCase(command)) { String address = getOwner().getAttribute(Attributes.SUBNET_ADDRESS); ((EntityLocal) getOwner().getRunningEntity()).setAttribute(Attributes.SUBNET_ADDRESS, address); diff --git a/docker/src/main/java/brooklyn/location/docker/DockerHostLocation.java b/docker/src/main/java/brooklyn/location/docker/DockerHostLocation.java index 1cac2d7c..cc2ce65f 100644 --- a/docker/src/main/java/brooklyn/location/docker/DockerHostLocation.java +++ b/docker/src/main/java/brooklyn/location/docker/DockerHostLocation.java @@ -66,7 +66,6 @@ import brooklyn.util.exceptions.Exceptions; import brooklyn.util.flags.SetFromFlag; import brooklyn.util.net.Cidr; -import brooklyn.util.os.Os; import brooklyn.util.ssh.BashCommands; import brooklyn.util.text.Strings; @@ -100,9 +99,6 @@ public class DockerHostLocation extends AbstractLocation implements MachineProvi @SetFromFlag("owner") private DockerHost dockerHost; - @SetFromFlag("repository") - private String repository; - @SetFromFlag("images") private ConcurrentMap images = Maps.newConcurrentMap(); @@ -118,15 +114,6 @@ public DockerHostLocation(Map properties) { } } - @Override - public void init() { - super.init(); - - if (repository == null) { - repository = machine.getId(); - } - } - public DockerContainerLocation obtain() throws NoMachinesAvailableException { return obtain(Maps.newLinkedHashMap()); } @@ -165,18 +152,17 @@ public DockerContainerLocation obtain(Map flags) throws NoMachinesAvailable Optional baseImage = Optional.fromNullable(entity.config().get(DockerAttributes.DOCKER_IMAGE_NAME)); String imageTag = Optional.fromNullable(entity.config().get(DockerAttributes.DOCKER_IMAGE_TAG)).or("latest"); // TODO incorporate more info - final String imageName = DockerUtils.imageName(entity, dockerfile, repository); - final String fullyQualifiedImageName = Os.mergePaths(repository, imageName); + final String imageName = DockerUtils.imageName(entity, dockerfile); // Lookup image ID or build new image from Dockerfile LOG.info("ImageName for entity {}: {}", entity, imageName); - if (dockerHost.getImageNamed(fullyQualifiedImageName, imageTag).isPresent()) { + if (dockerHost.getImageNamed(imageName, imageTag).isPresent()) { // Wait until committed before continuing - Brooklyn may be midway through its creation. waitForImage(imageName); // Look up imageId again - imageId = dockerHost.getImageNamed(fullyQualifiedImageName, imageTag).get(); + imageId = dockerHost.getImageNamed(imageName, imageTag).get(); LOG.info("Found image {} for entity: {}", imageName, imageId); // Skip install phase @@ -202,7 +188,7 @@ public DockerContainerLocation obtain(Map flags) throws NoMachinesAvailable // Tag the image name and create its latch images.putIfAbsent(imageName, new CountDownLatch(1)); - dockerHost.runDockerCommand(String.format("tag -f %s %s:latest", imageId, Os.mergePaths(repository, imageName))); + dockerHost.runDockerCommand(String.format("tag -f %s %s:latest", imageId, imageName)); } // Set subnet address pre install @@ -340,10 +326,6 @@ public DockerHost getOwner() { return dockerHost; } - public String getRepository() { - return repository; - } - public SshMachineLocation getMachine() { return machine; } diff --git a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java index 13d1484d..c72504db 100644 --- a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java +++ b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java @@ -16,20 +16,21 @@ */ package org.jclouds.docker.compute.options; -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; +import java.util.Map; + import org.jclouds.compute.options.TemplateOptions; import org.jclouds.domain.LoginCredentials; import org.jclouds.javax.annotation.Nullable; import org.jclouds.scriptbuilder.domain.Statement; -import java.util.List; -import java.util.Map; - -import static com.google.common.base.Objects.equal; -import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; /** * Contains options supported in the {@code ComputeService#runNode} operation on the diff --git a/examples/src/main/assembly/files/blueprints/docker-freehub-demo.yaml b/examples/src/main/assembly/files/blueprints/docker-freehub-demo.yaml new file mode 100644 index 00000000..5242c398 --- /dev/null +++ b/examples/src/main/assembly/files/blueprints/docker-freehub-demo.yaml @@ -0,0 +1,26 @@ +# Copyright 2014-2015 by Cloudsoft Corporation Limited +# +# Licensed 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. + +id: docker-freehub +name: "Docker Hub Freehub Application" +origin: "https://registry.hub.docker.com/u/bikebike/freehub/" +locations: +- my-docker-cloud + +services: +- type: docker:bikebike/freehub + openPorts: + - 3000 + directPorts: + - 3000 From 7d95bfd5ca84df2667e5aeab42651dba58e43d11 Mon Sep 17 00:00:00 2001 From: Andrew Kennedy Date: Thu, 9 Apr 2015 16:03:38 +0100 Subject: [PATCH 3/5] Set the container name using config or from Docker inspect --- .../entity/container/DockerAttributes.java | 3 + .../container/docker/DockerContainer.java | 10 +- .../container/docker/DockerContainerImpl.java | 33 +++- .../DockerServiceTypeResolver.java | 166 +++++++++--------- .../application/VanillaDockerApplication.java | 3 + .../options/DockerTemplateOptions.java | 19 +- .../strategy/DockerComputeServiceAdapter.java | 4 - 7 files changed, 134 insertions(+), 104 deletions(-) diff --git a/docker/src/main/java/brooklyn/entity/container/DockerAttributes.java b/docker/src/main/java/brooklyn/entity/container/DockerAttributes.java index c20b28db..972f555b 100644 --- a/docker/src/main/java/brooklyn/entity/container/DockerAttributes.java +++ b/docker/src/main/java/brooklyn/entity/container/DockerAttributes.java @@ -67,6 +67,9 @@ private DockerAttributes() { } public static final AttributeSensorAndConfigKey DOCKER_HARDWARE_ID = ConfigKeys.newStringSensorAndConfigKey( "docker.hardwareId", "The ID of a Docker hardware type to use for a container", "small"); + public static final AttributeSensorAndConfigKey DOCKER_CONTAINER_NAME = ConfigKeys.newStringSensorAndConfigKey( + "docker.container.name", "The name of the Docker container"); + public static final ConfigKey DOCKER_PASSWORD = ConfigKeys.newConfigKeyWithPrefix("docker.", SshTool.PROP_PASSWORD); public static final ConfigKey DOCKER_USE_HOST_DNS_NAME = ConfigKeys.newBooleanConfigKey( diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainer.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainer.java index 7ae52df1..31c9eaed 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainer.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainer.java @@ -28,7 +28,6 @@ import brooklyn.entity.basic.MethodEffector; import brooklyn.entity.basic.SoftwareProcess; import brooklyn.entity.container.DockerAttributes; -import brooklyn.entity.container.DockerUtils; import brooklyn.entity.proxying.ImplementedBy; import brooklyn.entity.trait.HasShortName; import brooklyn.event.AttributeSensor; @@ -59,6 +58,9 @@ public interface DockerContainer extends BasicStartable, HasNetworkAddresses, Ha @SetFromFlag("infrastructure") AttributeSensorAndConfigKey DOCKER_INFRASTRUCTURE = DockerHost.DOCKER_INFRASTRUCTURE; + @SetFromFlag("containerName") + AttributeSensorAndConfigKey DOCKER_CONTAINER_NAME = DockerAttributes.DOCKER_CONTAINER_NAME; + @SetFromFlag("managed") ConfigKey MANAGED = DockerAttributes.MANAGED; @@ -98,10 +100,8 @@ public interface DockerContainer extends BasicStartable, HasNetworkAddresses, Ha AttributeSensorAndConfigKey ENTITY = ConfigKeys.newSensorAndConfigKey(Entity.class, "docker.container.entity", "The entity running in this Docker container"); - ConfigKey DOCKER_CONTAINER_NAME_FORMAT = ConfigKeys.newStringConfigKey("docker.container.nameFormat", - "Format for generating Docker container names", DockerUtils.DEFAULT_DOCKER_CONTAINER_NAME_FORMAT); - - AttributeSensor DOCKER_CONTAINER_NAME = Sensors.newStringSensor("docker.container.name", "The name of the Docker container"); + ConfigKey DOCKER_CONTAINER_NAME_FORMAT = ConfigKeys.newStringConfigKey( + "docker.container.nameFormat", "Format for generating Docker container names"); AttributeSensor IMAGE_ID = Sensors.newStringSensor("docker.container.image.id", "The Docker container image ID"); AttributeSensor IMAGE_NAME = Sensors.newStringSensor("docker.container.image.name", "The Docker container image name"); diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java index 011a5547..1f913056 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java @@ -84,8 +84,11 @@ import brooklyn.util.text.Strings; import brooklyn.util.time.Duration; +import com.google.common.base.CaseFormat; +import com.google.common.base.CharMatcher; import com.google.common.base.Functions; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; @@ -104,9 +107,16 @@ public void init() { super.init(); AtomicInteger counter = config().get(DOCKER_INFRASTRUCTURE).getAttribute(DockerInfrastructure.DOCKER_CONTAINER_COUNTER); - String dockerContainerName = format(config().get(DockerContainer.DOCKER_CONTAINER_NAME_FORMAT), getId(), counter.incrementAndGet()); - setDisplayName(dockerContainerName); - setAttribute(DOCKER_CONTAINER_NAME, dockerContainerName); + String dockerContainerName = config().get(DOCKER_CONTAINER_NAME); + String dockerContainerNameFormat = config().get(DOCKER_CONTAINER_NAME_FORMAT); + if (Strings.isBlank(dockerContainerName) && Strings.isNonBlank(dockerContainerNameFormat)) { + dockerContainerName = format(dockerContainerNameFormat, getId(), counter.incrementAndGet()); + } + if (Strings.isNonBlank(dockerContainerName)) { + dockerContainerName = CharMatcher.BREAKING_WHITESPACE.trimAndCollapseFrom(dockerContainerName, '-'); + setDisplayName(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, dockerContainerName)); + setAttribute(DOCKER_CONTAINER_NAME, dockerContainerName); + } ConfigToAttributes.apply(this, DOCKER_INFRASTRUCTURE); ConfigToAttributes.apply(this, DOCKER_HOST); @@ -114,10 +124,21 @@ public void init() { } protected void connectSensors() { - // is this swappable for a feed that runs one command rather than three? status = FunctionFeed.builder() .entity(this) .period(Duration.seconds(15)) + .poll(new FunctionPollConfig(DOCKER_CONTAINER_NAME) + .period(Duration.minutes(1)) + .callable(new Callable() { + @Override + public String call() throws Exception { + String containerId = getContainerId(); + if (containerId == null) return ""; + String name = getDockerHost().runDockerCommand("inspect -f {{.Name}} " + containerId); + return Strings.removeFromStart(name, "/"); + } + }) + .onFailureOrException(Functions.constant(""))) .poll(new FunctionPollConfig(SERVICE_UP) .callable(new Callable() { @Override @@ -396,6 +417,10 @@ public DockerContainerLocation createLocation(Map flags) { // Configure the container options based on the host and the running entity DockerTemplateOptions options = getDockerTemplateOptions(); + String containerName = getAttribute(DOCKER_CONTAINER_NAME); + if (!Strings.isBlank(containerName)) { + options.nodeNames(ImmutableList.of(containerName)); + } // put these fields on the location so it has the info it needs to create the subnet Map dockerFlags = MutableMap.builder() diff --git a/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java b/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java index 142da5b2..4ae5bcd1 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/application/DockerServiceTypeResolver.java @@ -1,81 +1,85 @@ -/* - * 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 brooklyn.entity.container.docker.application; - -import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; -import io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver; -import io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver; -import io.brooklyn.camp.spi.PlatformComponentTemplate; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.catalog.CatalogItem; -import brooklyn.entity.Entity; -import brooklyn.entity.container.DockerAttributes; -import brooklyn.entity.proxying.EntitySpec; -import brooklyn.util.text.Strings; - -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; - -/** - * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code docker:} - * to Brooklyn {@link EntitySpec} instances. - */ -public class DockerServiceTypeResolver extends BrooklynServiceTypeResolver { - - private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class); - - public static final String PREFIX = "docker"; - - @Override - public String getTypePrefix() { return PREFIX; } - - @Override - public String getBrooklynType(String serviceType) { - return VanillaDockerApplication.class.getName(); - } - - // docker: items are not in catalog - @Override - public CatalogItem> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) { - return null; - } - - @Override - public void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec spec) { - String dockerServiceType = Strings.removeFromStart(resolver.getDeclaredType(), PREFIX + ":"); - List parts = Splitter.on(":").splitToList(dockerServiceType); - if (parts.isEmpty() || parts.size() > 2) { - throw new IllegalArgumentException("Docker serviceType cannot be parsed: " + dockerServiceType); - } - String imageName = Iterables.get(parts, 0); - String imageTag = Iterables.get(parts, 1, "latest"); - log.debug("Creating Docker service entity with image {} and tag {}", imageName, imageTag); - spec.configure(DockerAttributes.DOCKER_IMAGE_NAME, imageName); - if (parts.size() == 2) { - spec.configure(DockerAttributes.DOCKER_IMAGE_TAG, imageTag); - } - super.decorateSpec(resolver, spec); - } - -} +/* + * 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 brooklyn.entity.container.docker.application; + +import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; +import io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver; +import io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver; +import io.brooklyn.camp.spi.PlatformComponentTemplate; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.catalog.CatalogItem; +import brooklyn.entity.Entity; +import brooklyn.entity.container.DockerAttributes; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.util.text.Strings; + +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; + +/** + * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code docker:} + * to Brooklyn {@link EntitySpec} instances. + */ +public class DockerServiceTypeResolver extends BrooklynServiceTypeResolver { + + private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class); + + public static final String PREFIX = "docker"; + + @Override + public String getTypePrefix() { return PREFIX; } + + @Override + public String getBrooklynType(String serviceType) { + return VanillaDockerApplication.class.getName(); + } + + /** Docker items are not in catalog. */ + @Override + public CatalogItem> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) { + return null; + } + + @Override + public void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec spec) { + String dockerServiceType = Strings.removeFromStart(resolver.getDeclaredType(), PREFIX + ":"); + List parts = Splitter.on(":").splitToList(dockerServiceType); + if (parts.isEmpty() || parts.size() > 2) { + throw new IllegalArgumentException("Docker serviceType cannot be parsed: " + dockerServiceType); + } + String imageName = Iterables.get(parts, 0); + String imageTag = Iterables.get(parts, 1, "latest"); + log.debug("Creating Docker service entity with image {} and tag {}", imageName, imageTag); + spec.configure(DockerAttributes.DOCKER_IMAGE_NAME, imageName); + if (parts.size() == 2) { + spec.configure(DockerAttributes.DOCKER_IMAGE_TAG, imageTag); + } + if (resolver.getAttrs().containsKey("id")) { + String containerName = (String) resolver.getAttrs().getStringKey("id"); + spec.configure(DockerAttributes.DOCKER_CONTAINER_NAME, containerName); + } + super.decorateSpec(resolver, spec); + } + +} diff --git a/docker/src/main/java/brooklyn/entity/container/docker/application/VanillaDockerApplication.java b/docker/src/main/java/brooklyn/entity/container/docker/application/VanillaDockerApplication.java index 6dbed362..7d2482b1 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/application/VanillaDockerApplication.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/application/VanillaDockerApplication.java @@ -41,6 +41,9 @@ public interface VanillaDockerApplication extends VanillaSoftwareProcess { @SetFromFlag("dockerfileUrl") ConfigKey DOCKERFILE_URL = DockerAttributes.DOCKERFILE_URL; + @SetFromFlag("containerName") + ConfigKey CONTAINER_NAME = DockerContainer.DOCKER_CONTAINER_NAME.getConfigKey(); + @SetFromFlag("imageName") ConfigKey IMAGE_NAME = DockerAttributes.DOCKER_IMAGE_NAME.getConfigKey(); diff --git a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java index c72504db..13d1484d 100644 --- a/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java +++ b/docker/src/main/java/org/jclouds/docker/compute/options/DockerTemplateOptions.java @@ -16,21 +16,20 @@ */ package org.jclouds.docker.compute.options; -import static com.google.common.base.Objects.equal; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.List; -import java.util.Map; - +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.domain.LoginCredentials; import org.jclouds.javax.annotation.Nullable; import org.jclouds.scriptbuilder.domain.Statement; -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; /** * Contains options supported in the {@code ComputeService#runNode} operation on the diff --git a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java index 6da2bc0a..534ddf9b 100644 --- a/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java +++ b/docker/src/main/java/org/jclouds/docker/compute/strategy/DockerComputeServiceAdapter.java @@ -125,10 +125,6 @@ public NodeAndInitialCredentials createNodeWithGroupEncodedIntoName(S containerConfigBuilder.volumes(volumes); } - if (templateOptions.getEnv().isPresent()) { - containerConfigBuilder.env(templateOptions.getEnv().get()); - } - Config containerConfig = containerConfigBuilder.build(); logger.debug(">> creating new container with containerConfig(%s)", containerConfig); From ec4d43f490967828f6924a4b43328650de5f0b72 Mon Sep 17 00:00:00 2001 From: Andrew Kennedy Date: Thu, 9 Apr 2015 20:04:43 +0100 Subject: [PATCH 4/5] Update micro-service examples to use both Dockerfile and image --- .../container/docker/DockerContainerImpl.java | 9 ++- examples/src/main/assembly/conf/catalog.xml | 6 +- ...ub-demo.yaml => docker-jboss-wildfly.yaml} | 15 +++-- .../example/MicroServiceDockerfile.java | 55 +++++++++++++++++++ ...croService.java => MicroServiceImage.java} | 12 ++-- 5 files changed, 82 insertions(+), 15 deletions(-) rename examples/src/main/assembly/files/blueprints/{docker-freehub-demo.yaml => docker-jboss-wildfly.yaml} (75%) create mode 100644 examples/src/main/java/brooklyn/clocker/example/MicroServiceDockerfile.java rename examples/src/main/java/brooklyn/clocker/example/{MicroService.java => MicroServiceImage.java} (85%) diff --git a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java index 1f913056..6516db3a 100644 --- a/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java +++ b/docker/src/main/java/brooklyn/entity/container/docker/DockerContainerImpl.java @@ -417,8 +417,13 @@ public DockerContainerLocation createLocation(Map flags) { // Configure the container options based on the host and the running entity DockerTemplateOptions options = getDockerTemplateOptions(); - String containerName = getAttribute(DOCKER_CONTAINER_NAME); - if (!Strings.isBlank(containerName)) { + + // Check the running entity for alternative container name + String containerName = getRunningEntity().config().get(DOCKER_CONTAINER_NAME); + if (Strings.isBlank(containerName)) { + containerName = getAttribute(DOCKER_CONTAINER_NAME); + } + if (Strings.isNonBlank(containerName)) { options.nodeNames(ImmutableList.of(containerName)); } diff --git a/examples/src/main/assembly/conf/catalog.xml b/examples/src/main/assembly/conf/catalog.xml index 22a80b79..95449799 100644 --- a/examples/src/main/assembly/conf/catalog.xml +++ b/examples/src/main/assembly/conf/catalog.xml @@ -40,10 +40,14 @@ Node.JS Todo Application, with a Redis store classpath://nodejs-logo.png -