You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by m4...@apache.org on 2017/09/29 09:47:40 UTC
[3/6] brooklyn-library git commit: Move chef from brooklyn—software-base to own module
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
new file mode 100644
index 0000000..68a1d50
--- /dev/null
+++ b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes.wrapBash;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Strings;
+import com.google.common.net.HostAndPort;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.effector.EffectorTasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.Jsonya;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.ssh.BashCommands;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.gson.GsonBuilder;
+
+public class KnifeConvergeTaskFactory<RET> extends KnifeTaskFactory<RET> {
+
+ private static final Logger log = LoggerFactory.getLogger(KnifeConvergeTaskFactory.class);
+
+ protected Function<? super Entity,String> runList;
+ protected Map<Object, Object> knifeAttributes = new MutableMap<Object, Object>();
+ protected List<String> extraBootstrapParameters = MutableList.of();
+ protected Boolean sudo;
+ protected Boolean runTwice;
+ protected String nodeName;
+ protected Integer port;
+ /** null means nothing specified, use user supplied or machine default;
+ * false means use machine default (disallow user supplied);
+ * true means use knife default (omit the argument and disallow user supplied)
+ */
+ protected Boolean portOmittedToUseKnifeDefault;
+
+ public KnifeConvergeTaskFactory(String taskName) {
+ super(taskName);
+ }
+
+ @Override
+ protected KnifeConvergeTaskFactory<RET> self() {
+ return this;
+ }
+
+ /** construct the knife command, based on the settings on other methods
+ * (called when instantiating the script, after all parameters sent)
+ */
+ @Override
+ protected List<String> initialKnifeParameters() {
+ // runs inside the task so can detect entity/machine at runtime
+ MutableList<String> result = new MutableList<String>();
+ SshMachineLocation machine = EffectorTasks.findSshMachine();
+
+ result.add("bootstrap");
+ result.addAll(extraBootstrapParameters);
+
+ HostAndPort hostAndPort = machine.getSshHostAndPort();
+ result.add(wrapBash(hostAndPort.getHostText()));
+ Integer whichPort = knifeWhichPort(hostAndPort);
+ if (whichPort!=null)
+ result.add("-p "+whichPort);
+
+ result.add("-x "+wrapBash(checkNotNull(machine.getUser(), "user")));
+
+ File keyfile = ChefServerTasks.extractKeyFile(machine);
+ if (keyfile!=null) result.add("-i "+keyfile.getPath());
+ else result.add("-P "+checkNotNull(machine.findPassword(), "No password or private key data for "+machine));
+
+ result.add("--no-host-key-verify");
+
+ if (sudo != Boolean.FALSE) result.add("--sudo");
+
+ if (!Strings.isNullOrEmpty(nodeName)) {
+ result.add("--node-name");
+ result.add(nodeName);
+ }
+
+ result.add("-r "+wrapBash(runList.apply(entity())));
+
+ if (!knifeAttributes.isEmpty())
+ result.add("-j "+wrapBash(new GsonBuilder().create()
+ .toJson(knifeAttributes)));
+
+ return result;
+ }
+
+ /** whether knife should attempt to run twice;
+ * see {@link ChefConfig#CHEF_RUN_CONVERGE_TWICE} */
+ public KnifeConvergeTaskFactory<RET> knifeRunTwice(boolean runTwice) {
+ this.runTwice = runTwice;
+ return self();
+ }
+
+ /** whether to pass --sudo to knife; default true */
+ public KnifeConvergeTaskFactory<RET> knifeSudo(boolean sudo) {
+ this.sudo = sudo;
+ return self();
+ }
+
+ /** what node name to pass to knife; default = null, meaning chef-client will pick the node name */
+ public KnifeConvergeTaskFactory<RET> knifeNodeName(String nodeName) {
+ this.nodeName = nodeName;
+ return self();
+ }
+
+ /** tell knife to use an explicit port */
+ public KnifeConvergeTaskFactory<RET> knifePort(int port) {
+ if (portOmittedToUseKnifeDefault!=null) {
+ log.warn("Port "+port+" specified to "+this+" for when already explicitly told to use a default (overriding previous); see subsequent warning for more details");
+ }
+ this.port = port;
+ return self();
+ }
+
+ /** omit the port parameter altogether (let knife use its default) */
+ public KnifeConvergeTaskFactory<RET> knifePortUseKnifeDefault() {
+ if (port!=null) {
+ log.warn("knifePortUseKnifeDefault specified to "+this+" when already told to use "+port+" explicitly (overriding previous); see subsequent warning for more details");
+ port = -1;
+ }
+ portOmittedToUseKnifeDefault = true;
+ return self();
+ }
+
+ /** use the default port known to brooklyn for the target machine for ssh */
+ public KnifeConvergeTaskFactory<RET> knifePortUseMachineSshPort() {
+ if (port!=null) {
+ log.warn("knifePortUseMachineSshPort specified to "+this+" when already told to use "+port+" explicitly (overriding previous); see subsequent warning for more details");
+ port = -1;
+ }
+ portOmittedToUseKnifeDefault = false;
+ return self();
+ }
+
+ protected Integer knifeWhichPort(HostAndPort hostAndPort) {
+ if (port==null) {
+ if (Boolean.TRUE.equals(portOmittedToUseKnifeDefault))
+ // user has explicitly said to use knife default, omitting port here
+ return null;
+ // default is to use the machine port
+ return hostAndPort.getPort();
+ }
+ if (port==-1) {
+ // port was supplied by user, then portDefault (true or false)
+ port = null;
+ Integer whichPort = knifeWhichPort(hostAndPort);
+ log.warn("knife port conflicting instructions for "+this+" at entity "+entity()+" on "+hostAndPort+"; using default ("+whichPort+")");
+ return whichPort;
+ }
+ if (portOmittedToUseKnifeDefault!=null) {
+ // portDefault was specified (true or false), then overridden with a port
+ log.warn("knife port conflicting instructions for "+this+" at entity "+entity()+" on "+hostAndPort+"; using supplied port "+port);
+ }
+ // port was supplied by user, use that
+ return port;
+ }
+
+ /** parameters to pass to knife after the bootstrap command */
+ public KnifeConvergeTaskFactory<RET> knifeAddExtraBootstrapParameters(String extraBootstrapParameter1, String ...extraBootstrapParameters) {
+ this.extraBootstrapParameters.add(extraBootstrapParameter1);
+ for (String p: extraBootstrapParameters)
+ this.extraBootstrapParameters.add(p);
+ return self();
+ }
+
+ /** function supplying the run list to be passed to knife, evaluated at the last moment */
+ public KnifeConvergeTaskFactory<RET> knifeRunList(Function<? super Entity, String> runList) {
+ this.runList = runList;
+ return self();
+ }
+ public KnifeConvergeTaskFactory<RET> knifeRunList(String runList) {
+ this.runList = Functions.constant(runList);
+ return self();
+ }
+
+ /** includes the given attributes in the attributes to be passed to chef;
+ * when combining with other attributes, this uses {@link Jsonya} semantics to add
+ * (a deep add, combining lists and maps) */
+ public KnifeConvergeTaskFactory<RET> knifeAddAttributes(Map<? extends Object, ? extends Object> attributes) {
+ if (attributes!=null && !attributes.isEmpty()) {
+ Jsonya.of(knifeAttributes).add(attributes);
+ }
+ return self();
+ }
+
+ @Override
+ protected String buildKnifeCommand(int knifeCommandIndex) {
+ String result = super.buildKnifeCommand(knifeCommandIndex);
+ if (Boolean.TRUE.equals(runTwice))
+ result = BashCommands.alternatives(result, result);
+ return result;
+ }
+
+ @Override
+ public <T2> KnifeConvergeTaskFactory<T2> returning(ScriptReturnType type) {
+ return (KnifeConvergeTaskFactory<T2>) super.<T2>returning(type);
+ }
+
+ @Override
+ public <RET2> KnifeConvergeTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
+ return (KnifeConvergeTaskFactory<RET2>) super.returning(resultTransformation);
+ }
+
+ @Override
+ public KnifeConvergeTaskFactory<Boolean> returningIsExitCodeZero() {
+ return (KnifeConvergeTaskFactory<Boolean>) super.returningIsExitCodeZero();
+ }
+
+ @Override
+ public KnifeConvergeTaskFactory<String> requiringZeroAndReturningStdout() {
+ return (KnifeConvergeTaskFactory<String>) super.requiringZeroAndReturningStdout();
+ }
+
+ @Override
+ public KnifeConvergeTaskFactory<RET> knifeAddParameters(String word1, String ...words) {
+ super.knifeAddParameters(word1, words);
+ return self();
+ }
+
+ // TODO other methods from KnifeTaskFactory will return KTF class not KCTF;
+ // should make it generic so it returns the right type...
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java
new file mode 100644
index 0000000..2623a19
--- /dev/null
+++ b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.core.internal.ssh.process.ProcessTool;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.core.task.system.internal.SystemProcessTaskFactory;
+import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes;
+
+import com.google.common.base.Function;
+
+/** A factory which acts like {@link ProcessTaskFactory} with special options for knife.
+ * Typical usage is to {@link #addKnifeParameters(String)}s for the knife command to be run.
+ * You can also {@link #add(String...)} commands as needed; these will run *before* knife,
+ * unless you addKnifeCommandHere().
+ * <p>
+ * This impl will use sensible defaults, including {@link ConfigKey}s on the context entity,
+ * for general knife config but not specific commands etc. It supports:
+ * <li> {@link ChefConfig#KNIFE_EXECUTABLE}
+ * <li> {@link ChefConfig#KNIFE_CONFIG_FILE}
+ * <p>
+ * (Other fields will typically be used by methods calling to this factory.)
+ * */
+// see e.g. http://docs.opscode.com/knife_bootstrap.html
+public class KnifeTaskFactory<RET> extends SystemProcessTaskFactory<KnifeTaskFactory<RET>, RET>{
+
+ private static String KNIFE_PLACEHOLDER = "<knife command goes here 1234>";
+ public final String taskName;
+ protected String knifeExecutable;
+ protected List<String> knifeParameters = new ArrayList<String>();
+ protected String knifeConfigFile;
+ protected String knifeSetupCommands;
+ protected Boolean throwOnCommonKnifeErrors;
+
+ public KnifeTaskFactory(String taskName) {
+ this.taskName = taskName;
+ summary(taskName);
+ // knife setup usually requires a login shell
+ config.put(ProcessTool.PROP_LOGIN_SHELL, true);
+ }
+
+ @Override
+ public List<Function<ProcessTaskWrapper<?>, Void>> getCompletionListeners() {
+ MutableList<Function<ProcessTaskWrapper<?>, Void>> result = MutableList.copyOf(super.getCompletionListeners());
+ if (throwOnCommonKnifeErrors != Boolean.FALSE)
+ insertKnifeCompletionListenerIntoCompletionListenersList(result);
+ return result.asUnmodifiable();
+ }
+
+ public KnifeTaskFactory<RET> notThrowingOnCommonKnifeErrors() {
+ throwOnCommonKnifeErrors = false;
+ return self();
+ }
+
+ protected void insertKnifeCompletionListenerIntoCompletionListenersList(List<Function<ProcessTaskWrapper<?>, Void>> listeners) {
+ // give a nice warning if chef/knife not set up correctly
+ Function<ProcessTaskWrapper<?>, Void> propagateIfKnifeConfigFileMissing = new Function<ProcessTaskWrapper<?>, Void>() {
+ @Override
+ public Void apply(@Nullable ProcessTaskWrapper<?> input) {
+ if (input.getExitCode()!=0 && input.getStderr().indexOf("WARNING: No knife configuration file found")>=0) {
+ String myConfig = knifeConfigFileOption();
+ if (Strings.isEmpty(myConfig))
+ throw new IllegalStateException("Config file for Chef knife must be specified in "+ChefConfig.KNIFE_CONFIG_FILE+" (or valid knife default set up)");
+ else
+ throw new IllegalStateException("Error reading config file for Chef knife ("+myConfig+") -- does it exist?");
+ }
+ return null;
+ }
+ };
+ listeners.add(propagateIfKnifeConfigFileMissing);
+ }
+
+
+ @Override
+ public ProcessTaskWrapper<RET> newTask() {
+ return new SystemProcessTaskWrapper("Knife");
+ }
+
+ /** Inserts the knife command at the current place in the list.
+ * Can be run multiple times. The knife command added at the end of the list
+ * if this is not invoked (and it is the only command if nothing is {@link #add(String...)}ed.
+ */
+ public KnifeTaskFactory<RET> addKnifeCommandToScript() {
+ add(KNIFE_PLACEHOLDER);
+ return self();
+ }
+
+ @Override
+ public List<String> getCommands() {
+ MutableList<String> result = new MutableList<String>();
+ String setupCommands = knifeSetupCommands();
+ if (setupCommands != null && Strings.isNonBlank(setupCommands))
+ result.add(setupCommands);
+ int numKnifes = 0;
+ for (String c: super.getCommands()) {
+ if (c==KNIFE_PLACEHOLDER)
+ result.add(buildKnifeCommand(numKnifes++));
+ else
+ result.add(c);
+ }
+ if (numKnifes==0)
+ result.add(buildKnifeCommand(numKnifes++));
+ return result.asUnmodifiable();
+ }
+
+ /** creates the command for running knife.
+ * in some cases knife may be added multiple times,
+ * and in that case the parameter here tells which time it is being added,
+ * on a single run. */
+ protected String buildKnifeCommand(int knifeCommandIndex) {
+ MutableList<String> words = new MutableList<String>();
+ words.add(knifeExecutable());
+ words.addAll(initialKnifeParameters());
+ words.addAll(knifeParameters());
+ String x = knifeConfigFileOption();
+ if (Strings.isNonBlank(x)) words.add(knifeConfigFileOption());
+ return Strings.join(words, " ");
+ }
+
+ /** allows a way for subclasses to build up parameters at the start */
+ protected List<String> initialKnifeParameters() {
+ return new MutableList<String>();
+ }
+
+ @Nullable /** callers should allow this to be null so task can be used outside of an entity */
+ protected Entity entity() {
+ return BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
+ }
+ protected <T> T entityConfig(ConfigKey<T> key) {
+ Entity entity = entity();
+ if (entity!=null)
+ return entity.getConfig(key);
+ return null;
+ }
+
+ public KnifeTaskFactory<RET> knifeExecutable(String knifeExecutable) {
+ this.knifeExecutable = knifeExecutable;
+ return this;
+ }
+
+ protected String knifeExecutable() {
+ if (knifeExecutable!=null) return knifeExecutable;
+
+ String knifeExecFromConfig = entityConfig(ChefConfig.KNIFE_EXECUTABLE);
+ if (knifeExecFromConfig!=null) return BashStringEscapes.wrapBash(knifeExecFromConfig);
+
+ // assume on the path, if executable not set
+ return "knife";
+ }
+
+ protected List<String> knifeParameters() {
+ return knifeParameters;
+ }
+
+ public KnifeTaskFactory<RET> knifeAddParameters(String word1, String ...words) {
+ knifeParameters.add(word1);
+ for (String w: words)
+ knifeParameters.add(w);
+ return self();
+ }
+
+ public KnifeTaskFactory<RET> knifeConfigFile(String knifeConfigFile) {
+ this.knifeConfigFile = knifeConfigFile;
+ return self();
+ }
+
+ @Nullable
+ protected String knifeConfigFileOption() {
+ if (knifeConfigFile!=null) return "-c "+knifeConfigFile;
+
+ String knifeConfigFileFromConfig = entityConfig(ChefConfig.KNIFE_CONFIG_FILE);
+ if (knifeConfigFileFromConfig!=null) return "-c "+BashStringEscapes.wrapBash(knifeConfigFileFromConfig);
+
+ // if not supplied will use global config
+ return null;
+ }
+
+ public KnifeTaskFactory<RET> knifeSetupCommands(String knifeSetupCommands) {
+ this.knifeSetupCommands = knifeSetupCommands;
+ return self();
+ }
+
+ @Nullable
+ protected String knifeSetupCommands() {
+ if (knifeSetupCommands!=null) return knifeSetupCommands;
+
+ String knifeSetupCommandsFromConfig = entityConfig(ChefConfig.KNIFE_SETUP_COMMANDS);
+ if (knifeSetupCommandsFromConfig!=null) return knifeSetupCommandsFromConfig;
+
+ // if not supplied will use global config
+ return null;
+ }
+
+ @Override
+ public <T2> KnifeTaskFactory<T2> returning(ScriptReturnType type) {
+ return (KnifeTaskFactory<T2>) super.<T2>returning(type);
+ }
+
+ @Override
+ public <RET2> KnifeTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
+ return (KnifeTaskFactory<RET2>) super.returning(resultTransformation);
+ }
+
+ @Override
+ public KnifeTaskFactory<Boolean> returningIsExitCodeZero() {
+ return (KnifeTaskFactory<Boolean>) super.returningIsExitCodeZero();
+ }
+
+ @Override
+ public KnifeTaskFactory<String> requiringZeroAndReturningStdout() {
+ return (KnifeTaskFactory<String>) super.requiringZeroAndReturningStdout();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/resolve/ChefEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/resolve/ChefEntitySpecResolver.java b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/resolve/ChefEntitySpecResolver.java
new file mode 100644
index 0000000..91e00ce
--- /dev/null
+++ b/software/cm/chef/src/main/java/org/apache/brooklyn/entity/chef/resolve/ChefEntitySpecResolver.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.resolve;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefEntity;
+
+public class ChefEntitySpecResolver extends AbstractEntitySpecResolver {
+ private static final String RESOLVER_NAME = "chef";
+
+ public ChefEntitySpecResolver() {
+ super(RESOLVER_NAME);
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ return EntitySpec.create(ChefEntity.class)
+ .configure(ChefConfig.CHEF_COOKBOOK_PRIMARY_NAME, getLocalType(type));
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver b/software/cm/chef/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver
new file mode 100644
index 0000000..cdd7af9
--- /dev/null
+++ b/software/cm/chef/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.brooklyn.entity.resolve.ChefEntitySpecResolver
+
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/software/cm/chef/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..4412687
--- /dev/null
+++ b/software/cm/chef/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright 2015 The Apache Software Foundation.
+
+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.
+-->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0"
+ xsi:schemaLocation="
+ http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
+ http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
+ ">
+
+ <bean id="chefEntitySpecResolver" scope="prototype"
+ class="org.apache.brooklyn.entity.resolve.ChefEntitySpecResolver"/>
+ <service id="chefEntitySpecResolverService" ref="chefEntitySpecResolver"
+ interface="org.apache.brooklyn.core.resolve.entity.EntitySpecResolver" />
+
+</blueprint>
+
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/main/resources/catalog.bom
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/main/resources/catalog.bom b/software/cm/chef/src/main/resources/catalog.bom
new file mode 100644
index 0000000..4322e23
--- /dev/null
+++ b/software/cm/chef/src/main/resources/catalog.bom
@@ -0,0 +1,26 @@
+# 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.
+
+brooklyn.catalog:
+ version: "0.12.0-SNAPSHOT" # BROOKLYN_VERSION
+ itemType: entity
+ items:
+ - id: org.apache.brooklyn.entity.chef.ChefEntity
+ item:
+ type: org.apache.brooklyn.entity.chef.ChefEntity
+ name: Chef Entity
+ description: Software managed by Chef
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefConfigsTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefConfigsTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefConfigsTest.java
new file mode 100644
index 0000000..dfdb85f
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefConfigsTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef;
+
+import java.util.Set;
+
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefConfigs;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ChefConfigsTest extends BrooklynAppUnitTestSupport {
+
+ @Test
+ public void testAddToRunList() {
+ ChefConfigs.addToLaunchRunList(app, "a", "b");
+ Set<? extends String> runs = app.getConfig(ChefConfig.CHEF_LAUNCH_RUN_LIST);
+ Assert.assertEquals(runs.size(), 2, "runs="+runs);
+ Assert.assertTrue(runs.contains("a"));
+ Assert.assertTrue(runs.contains("b"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java
new file mode 100644
index 0000000..ff389b0
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef;
+
+import java.io.File;
+import java.io.InputStream;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.core.ResourceUtils;
+import org.apache.brooklyn.util.io.FileUtil;
+import org.apache.brooklyn.util.stream.Streams;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+
+import com.google.common.io.Files;
+
+public class ChefLiveTestSupport extends BrooklynAppLiveTestSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(ChefLiveTestSupport.class);
+
+ protected MachineProvisioningLocation<? extends SshMachineLocation> targetLocation;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ targetLocation = createLocation();
+ }
+
+ protected MachineProvisioningLocation<? extends SshMachineLocation> createLocation() {
+ return createLocation(mgmt);
+ }
+
+ /** convenience for setting up a pre-built / fixed IP machine
+ * (because you might not want to set up Chef on localhost)
+ * and ensuring tests against Chef use the same configured location
+ **/
+ public static MachineProvisioningLocation<? extends SshMachineLocation> createLocation(ManagementContext mgmt) {
+ LocationSpec<?> bestLocation = mgmt.getLocationRegistry().getLocationSpec("named:ChefTests").orNull();
+ if (bestLocation==null) {
+ log.info("using AWS for chef tests because named:ChefTests does not exist");
+ bestLocation = mgmt.getLocationRegistry().getLocationSpec("jclouds:aws-ec2:us-east-1").orNull();
+ }
+ if (bestLocation==null) {
+ throw new IllegalStateException("Need a location called named:ChefTests or AWS configured for these tests");
+ }
+ @SuppressWarnings("unchecked")
+ MachineProvisioningLocation<? extends SshMachineLocation> result = (MachineProvisioningLocation<? extends SshMachineLocation>)
+ mgmt.getLocationManager().createLocation(bestLocation);
+ return result;
+ }
+
+ private static String defaultConfigFile = null;
+ public synchronized static String installBrooklynChefHostedConfig() {
+ if (defaultConfigFile!=null) return defaultConfigFile;
+ File tempDir = Files.createTempDir();
+ ResourceUtils r = ResourceUtils.create(ChefServerTasksIntegrationTest.class);
+ for (String f: new String[] { "knife.rb", "brooklyn-tests.pem", "brooklyn-validator.pem" }) {
+ InputStream in = r.getResourceFromUrl("classpath:///org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/"+f);
+ try {
+ FileUtil.copyTo(in, new File(tempDir, f));
+ } finally {
+ Streams.closeQuietly(in);
+ }
+ }
+ File knifeConfig = new File(tempDir, "knife.rb");
+ defaultConfigFile = knifeConfig.getPath();
+ return defaultConfigFile;
+ }
+
+ public static void installBrooklynChefHostedConfig(Entity entity) {
+ ((EntityInternal)entity).config().set(ChefConfig.KNIFE_CONFIG_FILE, ChefLiveTestSupport.installBrooklynChefHostedConfig());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
new file mode 100644
index 0000000..a7b5803
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefServerTasks;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.stream.StreamGobbler;
+import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/** Many tests expect knife on the path, but none require any configuration beyond that.
+ * They will use the Brooklyn registered account (which has been set up with mysql cookbooks and more).
+ * <p>
+ * Note this is a free account so cannot manage many nodes.
+ * You can use the credentials in src/test/resources/hosted-chef-brooklyn-credentials/
+ * to log in and configure the settings for our tests using knife. You can also log in at:
+ * <p>
+ * https://manage.opscode.com/
+ * <p>
+ * with credentials for those with need to know (which is a lot of people, but not everyone
+ * with access to this github repo!).
+ * <p>
+ * You can easily set up your own new account, for free; download the starter kit and
+ * point {@link ChefConfig#KNIFE_CONFIG_FILE} at the knife.rb.
+ * <p>
+ * Note that if you are porting an existing machine to be managed by a new chef account, you may need to do the following:
+ * <p>
+ * ON management machine:
+ * <li>knife client delete HOST # or bulk delete, but don't delete your validator! it is a PITA recreating and adding back all the permissions!
+ * <li>knife node delete HOST
+ * <p>
+ * ON machine being managed:
+ * <li>rm -rf /{etc,var}/chef
+ * <p>
+ * Note also that some tests require a location named:ChefLive to be set up in your brooklyn.properties.
+ * This can be a cloud (but will require frequent chef-node pruning) or a permanently set-up machine.
+ **/
+// TODO Does it really need to be a live test? When converting from ApplicationBuilder, preserved
+// existing behaviour of using the live BrooklynProperties.
+public class ChefServerTasksIntegrationTest extends BrooklynAppLiveTestSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(ChefServerTasksIntegrationTest.class);
+
+ /** @deprecated use {@link ChefLiveTestSupport} */
+ @Deprecated
+ public synchronized static String installBrooklynChefHostedConfig() {
+ return ChefLiveTestSupport.installBrooklynChefHostedConfig();
+ }
+
+ @Test(groups="Integration")
+ @SuppressWarnings("resource")
+ public void testWhichKnife() throws IOException, InterruptedException {
+ // requires that knife is installed on the path of login shells
+ Process p = Runtime.getRuntime().exec(new String[] { "bash", "-l", "-c", "which knife" });
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new StreamGobbler(p.getInputStream(), out, log).start();
+ new StreamGobbler(p.getErrorStream(), out, log).start();
+ log.info("bash -l -c 'which knife' gives exit code: "+p.waitFor());
+ Time.sleep(Duration.millis(1000));
+ log.info("output:\n"+out);
+ Assert.assertEquals(p.exitValue(), 0);
+ }
+
+ @Test(groups="Integration")
+ public void testKnifeWithoutConfig() {
+ // without config it shouldn't pass
+ // (assumes that knife global config is *not* installed on your machine)
+ ProcessTaskWrapper<Boolean> t = Entities.submit(app, ChefServerTasks.isKnifeInstalled());
+ log.info("isKnifeInstalled without config returned: "+t.get()+" ("+t.getExitCode()+")\n"+t.getStdout()+"\nERR:\n"+t.getStderr());
+ Assert.assertFalse(t.get());
+ }
+
+ @Test(groups="Integration")
+ public void testKnifeWithConfig() {
+ // requires that knife is installed on the path of login shells
+ // (creates the config in a temp space)
+ ChefLiveTestSupport.installBrooklynChefHostedConfig(app);
+ ProcessTaskWrapper<Boolean> t = Entities.submit(app, ChefServerTasks.isKnifeInstalled());
+ log.info("isKnifeInstalled *with* config returned: "+t.get()+" ("+t.getExitCode()+")\n"+t.getStdout()+"\nERR:\n"+t.getStderr());
+ Assert.assertTrue(t.get());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java
new file mode 100644
index 0000000..55fa4ff
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.entity.chef.ChefLiveTestSupport;
+import org.apache.brooklyn.entity.software.base.test.mysql.AbstractToyMySqlEntityTest;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+public abstract class AbstractChefToyMySqlEntityLiveTest extends AbstractToyMySqlEntityTest {
+
+ @Override
+ // mark as live here
+ @Test(groups = "Live")
+ public void testMySqlOnProvisioningLocation() throws Exception {
+ super.testMySqlOnProvisioningLocation();
+ }
+
+ @Override
+ protected MachineProvisioningLocation<? extends SshMachineLocation> createLocation() {
+ return ChefLiveTestSupport.createLocation(mgmt);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
new file mode 100644
index 0000000..a0bfba2
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.testng.annotations.Test;
+
+public class ChefSoloDriverMySqlEntityLiveTest extends AbstractChefToyMySqlEntityLiveTest {
+
+ // test here just so Eclipse IDE picks it up
+ @Override @Test(groups="Live")
+ public void testMySqlOnProvisioningLocation() throws Exception {
+ super.testMySqlOnProvisioningLocation();
+ }
+
+ @Override
+ protected Integer getPid(Entity mysql) {
+ ProcessTaskWrapper<Integer> t = Entities.submit(mysql, SshEffectorTasks.ssh("sudo cat "+ChefSoloDriverToyMySqlEntity.PID_FILE));
+ return Integer.parseInt(t.block().getStdout().trim());
+ }
+
+ @Override
+ protected Entity createMysql() {
+ return app.createAndManageChild(EntitySpec.create(Entity.class, ChefSoloDriverToyMySqlEntity.class).
+ additionalInterfaces(SoftwareProcess.class));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java
new file mode 100644
index 0000000..70b20ad
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.mgmt.TaskAdaptable;
+import org.apache.brooklyn.api.mgmt.TaskFactory;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefConfigs;
+import org.apache.brooklyn.entity.chef.ChefSoloDriver;
+import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
+import org.apache.brooklyn.feed.ssh.SshFeed;
+import org.apache.brooklyn.feed.ssh.SshPollConfig;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.time.Duration;
+
+@Deprecated /** @deprecated since 0.7.0 use see examples {Dynamic,Typed}ToyMySqlEntityChef */
+public class ChefSoloDriverToyMySqlEntity extends SoftwareProcessImpl implements ChefConfig {
+
+ public static final String PID_FILE = "/var/run/mysqld/mysqld.pid";
+ public static final ConfigKey<TaskFactory<? extends TaskAdaptable<Boolean>>> IS_RUNNING_TASK =
+ ConfigKeys.newConfigKeyWithDefault(ChefSoloDriver.IS_RUNNING_TASK,
+ SshEffectorTasks.isPidFromFileRunning(PID_FILE).runAsRoot());
+
+ public static final ConfigKey<TaskFactory<?>> STOP_TASK =
+ ConfigKeys.newConfigKeyWithDefault(ChefSoloDriver.STOP_TASK,
+ SshEffectorTasks.ssh("/etc/init.d/mysql stop").allowingNonZeroExitCode().runAsRoot());
+
+ private SshFeed upFeed;
+
+ @Override
+ public Class<?> getDriverInterface() {
+ return ChefSoloDriver.class;
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+
+ // TODO have a TaskFactoryFeed which reuses the IS_RUNNING_TASK
+ upFeed = SshFeed.builder().entity(this).period(Duration.FIVE_SECONDS.toMilliseconds())
+ .poll(new SshPollConfig<Boolean>(SERVICE_UP)
+ .command("ps -p `sudo cat /var/run/mysqld/mysqld.pid`")
+ .setOnSuccess(true).setOnFailureOrException(false))
+ .build();
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ // TODO nicer way to disconnect
+ if (upFeed != null) upFeed.stop();
+ super.disconnectSensors();
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ ChefConfigs.addToLaunchRunList(this, "mysql::server");
+ ChefConfigs.addToCookbooksFromGithub(this, "mysql", "build-essential", "openssl");
+ ChefConfigs.setLaunchAttribute(this, "mysql",
+ MutableMap.of()
+ .add("server_root_password", "MyPassword")
+ .add("server_debian_password", "MyPassword")
+ .add("server_repl_password", "MyPassword")
+ );
+
+ // TODO other attributes, eg:
+ // node['mysql']['port']
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java
new file mode 100644
index 0000000..0102f6e
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+public class DynamicChefAutodetectToyMySqlEntityLiveTest extends AbstractChefToyMySqlEntityLiveTest {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicChefAutodetectToyMySqlEntityLiveTest.class);
+
+ // test here just so Eclipse IDE picks it up
+ @Override @Test(groups="Live")
+ public void testMySqlOnProvisioningLocation() throws Exception {
+ super.testMySqlOnProvisioningLocation();
+ }
+
+ @Override
+ protected Entity createMysql() {
+ Entity mysql = app.createAndManageChild(DynamicToyMySqlEntityChef.spec());
+ log.debug("created "+mysql);
+ return mysql;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java
new file mode 100644
index 0000000..566a96e
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.entity.chef.ChefLiveTestSupport;
+import org.apache.brooklyn.entity.chef.ChefServerTasksIntegrationTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+/** Expects knife on the path, but will use Brooklyn registered account,
+ * and that account has the mysql recipe installed.
+ * <p>
+ * See {@link ChefServerTasksIntegrationTest} for more info. */
+public class DynamicChefServerToyMySqlEntityLiveTest extends AbstractChefToyMySqlEntityLiveTest {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicChefServerToyMySqlEntityLiveTest.class);
+
+ // test here just so Eclipse IDE picks it up
+ @Override @Test(groups="Live")
+ public void testMySqlOnProvisioningLocation() throws Exception {
+ super.testMySqlOnProvisioningLocation();
+ }
+
+ @Override
+ protected Entity createMysql() {
+ ChefLiveTestSupport.installBrooklynChefHostedConfig(app);
+ Entity mysql = app.createAndManageChild(DynamicToyMySqlEntityChef.specKnife());
+ log.debug("created "+mysql);
+ return mysql;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java
new file mode 100644
index 0000000..ba6c6d9
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+public class DynamicChefSoloToyMySqlEntityLiveTest extends AbstractChefToyMySqlEntityLiveTest {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicChefSoloToyMySqlEntityLiveTest.class);
+
+ // test here just so Eclipse IDE picks it up
+ @Override @Test(groups="Live")
+ public void testMySqlOnProvisioningLocation() throws Exception {
+ super.testMySqlOnProvisioningLocation();
+ }
+
+ @Override
+ protected Entity createMysql() {
+ Entity mysql = app.createAndManageChild(DynamicToyMySqlEntityChef.specSolo());
+ log.debug("created "+mysql);
+ return mysql;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java
new file mode 100644
index 0000000..2edd8a1
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.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 org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefConfigs;
+import org.apache.brooklyn.entity.chef.ChefEntity;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Builds up a MySql entity via chef using specs only */
+public class DynamicToyMySqlEntityChef implements ChefConfig {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicToyMySqlEntityChef.class);
+
+ protected static EntitySpec<? extends Entity> specBase() {
+ EntitySpec<ChefEntity> spec = EntitySpec.create(ChefEntity.class);
+
+ ChefConfigs.addToLaunchRunList(spec, "mysql::server");
+ spec.configure(PID_FILE, "/var/run/mysqld/mysql*.pid");
+ // init.d service name is sometimes mysql, sometimes mysqld, depending ubuntu/centos
+ // we use pid file above instead, but this (with the right name) could be used:
+// spec.configure(SERVICE_NAME, "mysql");
+
+ // chef mysql fails on first run but works on second if switching between server and solo modes
+ spec.configure(ChefConfig.CHEF_RUN_CONVERGE_TWICE, true);
+
+ // only used for solo, but safely ignored for knife
+ ChefConfigs.addToCookbooksFromGithub(spec, "mysql", "build-essential", "openssl");
+ // we always need dependent cookbooks set, and mysql requires password set
+ // (TODO for knife we might wish to prefer things from the server)
+ ChefConfigs.addLaunchAttributes(spec, MutableMap.of("mysql",
+ MutableMap.of()
+ .add("server_root_password", "MyPassword")
+ .add("server_debian_password", "MyPassword")
+ .add("server_repl_password", "MyPassword")
+ ));
+
+ return spec;
+ }
+
+ public static EntitySpec<? extends Entity> spec() {
+ EntitySpec<? extends Entity> spec = specBase();
+ log.debug("Created entity spec for MySql: "+spec);
+ return spec;
+ }
+
+ public static EntitySpec<? extends Entity> specSolo() {
+ EntitySpec<? extends Entity> spec = specBase();
+ spec.configure(ChefConfig.CHEF_MODE, ChefConfig.ChefModes.SOLO);
+ log.debug("Created entity spec for MySql: "+spec);
+ return spec;
+ }
+
+ public static EntitySpec<? extends Entity> specKnife() {
+ EntitySpec<? extends Entity> spec = specBase();
+ spec.configure(ChefConfig.CHEF_MODE, ChefConfig.ChefModes.KNIFE);
+ log.debug("Created entity spec for MySql: "+spec);
+ return spec;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java
new file mode 100644
index 0000000..c02dbc6
--- /dev/null
+++ b/software/cm/chef/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.chef.mysql;
+
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefEntityImpl;
+import org.apache.brooklyn.util.git.GithubUrls;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/** Illustrates how to define an entity using Java as a Java class, extending ChefEntityImpl */
+public class TypedToyMySqlEntityChef extends ChefEntityImpl {
+
+ @Override
+ public void init() {
+ super.init();
+
+ String password = "p4ssw0rd";
+
+ config().set(CHEF_COOKBOOK_PRIMARY_NAME, "mysql");
+ config().set(CHEF_COOKBOOK_URLS, ImmutableMap.of(
+ "mysql", GithubUrls.tgz("opscode-cookbooks", "mysql", "v4.0.12"),
+ "openssl", GithubUrls.tgz("opscode-cookbooks", "openssl", "v1.1.0"),
+ "mysql", GithubUrls.tgz("opscode-cookbooks", "build-essential", "v1.4.4")));
+
+ config().set(CHEF_LAUNCH_RUN_LIST, ImmutableSet.of("mysql::server"));
+ config().set(CHEF_LAUNCH_ATTRIBUTES, ImmutableMap.<String,Object>of(
+ "mysql", ImmutableMap.of(
+ "server_root_password", password,
+ "server_repl_password", password,
+ "server_debian_password", password)));
+
+ config().set(ChefConfig.PID_FILE, "/var/run/mysqld/mysqld.pid");
+
+ config().set(CHEF_MODE, ChefModes.SOLO);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-tests.pem
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-tests.pem b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-tests.pem
new file mode 100644
index 0000000..4ca4d00
--- /dev/null
+++ b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-tests.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEArJZcg6Y9BuPYuLWgcloS/cH6HzqQqQegW+5d7cgRZC1CCo4e
+GxVglEZXuko4N0PVK2E2khGiMEymVXWqmrHAnTSqV1COmRfxxOxGvmQRleDWMhED
+j2KoOwggwsaoHBEdrZ6NX+yv3iFiOS5fz3Klkt3kPXcXZJGiFsOtyZaSxK/m26no
+upS6ouChmk9TD8YcCQzdUGNAWwyzhiDg5DwqnnNQQUKvQyJuV/nyxwRMcpoNazca
+ghr2KalSF92sonnPzMz2gWhKxWVVbnTSafWQcWY+ov/TiyBHsLXO3/OrHaj7h+SF
+UUfWryHyqZI/eQeoWD/cPGtr8qVELIqhCq8OkQIDAQABAoIBAAS2Eg5x8kaG37qj
+Ep8sgEo3Clnh4mMK10DLL/s2s+rVJXFeUcoRelJx3SEzt3civeXyQGgaXSAOZ5f7
+n02bvpNMBb5eb5YURkBG5uN5ndVGjvJM7pjya385CJPoklw5x2Ke6mMM9fwNUz4W
+Wv0xtv1cW0emQZg4NYGDk/Hlz1nZG+y5j0esRlIiknYqdfuXtaQbVI/jGSyNXFVI
+uVkKCwq+k6HnIkjFEZdvQPRPaGMT4cMwczVr8hCIOfCJEVremEJ0GFnazr9iNEVu
+18YJzOEaqPLgVvjt59o+D+CoZS7U74WX6scCsFCkHLdnxlfNC/qkrn2SEaVyrfeP
+cqPLZJUCgYEA1qmmQzuNzWMhsOVty3EI4M2mePF0iM2P/wHc1ry9lddqdqTSGV7x
+NwzGNZ/OqN9UIR/3chyFXQuegz5VZxsrdIyxcgCmM2cDDxny3pr0Lct39gsWuc9g
+BhebUDP7PoF2g2f4AAllVR6atClwXoKfARoXlmbjfOJSB/q1zXWYNW8CgYEAzdJ/
+2o1B4iwDipKxJE2luuaMN4zqRbKdokBJYw0b1TOOcsyNwB5h0TGcJNFMuIqBeWCK
+J3wr7FTOfy3Qsbf3Vc5Le6NdaHomy7+HEwVMzyEPVNKumHqEL9U3Yheu5TVLLKMU
+rYBXXpoN/XXm9XxvRGhGu7Wu99ye37hIa4Qy+/8CgYB/JWlHdWTefJMeFibcU41w
+qh6qkEn4Jdner5nAz3Zz5G447BNN18CEXNqiNI/R0sYgALEuM9qCbDltf2RSd/Nb
+S2JnJh9LXv6e2T3TwHBVF6lsYNELKdu0gBMMhF2SflhWKSTp0KbmrgPwJoNaV4Aa
+xPunqDWiaOMxurwogDixnQKBgGgGQs5P5IOOIUARQeyKPgAHc8jDtMgDLX6KpUyl
+nHKV+yH0VpRKBsA3JabKDc+bWTLiYxDvxjdM6Y0Ht9mKlDxO5oGXoKckTaVeqMMp
+Q5fQKrKBRPMVwOd4COTP+XopBFSMG/BQ1Feg3v9CbreV65qUZWOLwOHPJJEHz7pf
+d3E7AoGBAMPkKjDuhU8YTpB6H4KlCM+9p/6yE7umoWMPJm70301XxBoQA8spkS3o
+K2s2xL7+MuppvLv0xqyZ1vtvqmUMrw/eisQWekGobEiutk+DuxegRlpUkH0s6CH4
+lypeh/FpGdLayAn84ALIEYhCsr0SnJtEL1MEO9qPKJY24Hl6ATCC
+-----END RSA PRIVATE KEY-----
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-validator.pem
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-validator.pem b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-validator.pem
new file mode 100644
index 0000000..7fb694c
--- /dev/null
+++ b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/brooklyn-validator.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA1L/awgkt+AxAHc76IeJAsZYj0ZoW8pP0Ff2SL8ZmkoGOT3C6
+d6DhQ8H194YTYNZ+w+D4K6DkNf8MqoFnQnLyQHlALd+giCE9mS1SUS0YBBdXbGh/
+320cosPqvMrT16nxbTLz7rgGNYSvgS5tnFYIADv4AzvXZMOZ20VXkDNCiqG0Pqy5
+qAMvmNGJNpDfERebdQUoZpqPJysJYXmy2cKYm5cfsDCxmL9iGyPjHazU6FizC50M
+SJ+ZGtqVEB/0d4p4u/pHAZQJCFdxJszHqBbYfQDFJso9lAdkM/11Tq5NtBH3cTPi
+SfcFIWLSS4qu1RcRmURRtsZTr/4FOKcYWpmLcwIDAQABAoIBACLzzi3YsjuxT4tW
+KNQORtCmOQZDiYea9Rvzx+OfddSWAlpcy9XBkaC/Kfjbhy1+r97ghAUu7q9MUrlk
+fyF0nwYmpXuj5MzYoTUcNAzwGqT5bLx7wp5jX7QB+fvAWuNwoSBuoZLTmvmJ7geM
+KCfqHnBjadCmMTH1zL4wez1Onp0FvRDXGPGjERQGptpejTL8PBaarzF2Ufewb/0z
+2/Icl1RAGHNkJHJjedL2mgtKHzW/JTBLcMjN1+PL4pLMriXCTP3VZZlezx8RXrnW
+DTFWe6G8gcPhYh0ni3wtoI/ENvXORg+wFXa2B/FKRObTu+vyYyvDgUSB2TI5LebX
+XsuWEEECgYEA/f9gkab9+m9JDz7AYDF4f+YzECdZwA0ntAnA5Qb/zWnjbcbtOMMF
+lNEm+m9J9GoorSpO9e/4Z61dtEsuX9Vr2tyKSnamNQT2vI+WIUIbGMWFq/VNi390
+o0jQWhEead/xu5BFbLEBD651+NBQGBCQi8slzOAL6jqP8qEGeaYaauECgYEA1m06
+wdHM3U5wwCGsyzTloGZ0LtTFO6oKYPpU/MItEESqVY1grFh5Sqa6tyJEq0jZSdKM
+eXzlqSyJQbaHd85PJnDkVnJVpdeqRj1eMHtv9+s3A8kOzSww+FL7KJHUrnNBZ7MK
+J7wdPtzYBFL124NAhbTaR6+Kv1ZSUpkGFRCV9NMCgYBtMy5BcJog4Vd3xnLO6HX2
+BvJNL53Wg9FeBhN4Y9n2Zl/xAmVa0f3ETWeEo/QXsMxsJpRsCA+0A0UWDnyRlyAX
+qFmMShaLFOc/ijvxcIpVzBX8KCp+nv12dgedsV5yBmXXTd+LK05Zf5gYsPa+YeDD
+OUO3IVv+B897cN9nzZHuAQKBgGIC44ycXUv7AsaPne/0adF7gze0wcKX4s6ZHie6
+ieaZvFIGoV2lwytAMrBq1YCFd+yqdNNDJ6bAWKzUxe8ZOkyT5YsuD8ASaB5bBqaa
+hX+I4Ei2qjFWNbwMEgllPxXOUOMZj1bCQYvuXj77vK1tvRxgojWKI5150381uvX9
+8s1JAoGBAO73ig60VNqPTHg1KDZ7SdAW0KbNiAV+xojvW9pkH5M1vCllz+lpeW1l
+jZFbnL013r5UvzRgwqIuw4t+gZikfIZgPwP8Z2BGtIzNiIHy/RLzOawsPTTXczZA
+hHI2e54G9DgCi8h4LXhFavVykTkNTP62S6za4VTEjxERdWxIBnfL
+-----END RSA PRIVATE KEY-----
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/knife.rb
----------------------------------------------------------------------
diff --git a/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/knife.rb b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/knife.rb
new file mode 100644
index 0000000..d52e492
--- /dev/null
+++ b/software/cm/chef/src/test/resources/org/apache/brooklyn/entity/chef/hosted-chef-brooklyn-credentials/knife.rb
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+current_dir = File.dirname(__FILE__)
+log_level :info
+log_location STDOUT
+node_name "brooklyn-tests"
+client_key "#{current_dir}/brooklyn-tests.pem"
+validation_client_name "brooklyn-validator"
+validation_key "#{current_dir}/brooklyn-validator.pem"
+chef_server_url "https://api.opscode.com/organizations/brooklyn"
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/cm/pom.xml
----------------------------------------------------------------------
diff --git a/software/cm/pom.xml b/software/cm/pom.xml
index 7e3fd3b..273dd41 100644
--- a/software/cm/pom.xml
+++ b/software/cm/pom.xml
@@ -71,10 +71,9 @@
</mailingLists>
<modules>
-
+ <module>chef</module>
<module>salt</module>
<module>ansible</module>
-
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/737dc8a9/software/database/pom.xml
----------------------------------------------------------------------
diff --git a/software/database/pom.xml b/software/database/pom.xml
index 7407397..614bee5 100644
--- a/software/database/pom.xml
+++ b/software/database/pom.xml
@@ -70,6 +70,11 @@
</dependency>
<dependency>
<groupId>org.apache.brooklyn</groupId>
+ <artifactId>brooklyn-software-cm-chef</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.brooklyn</groupId>
<artifactId>brooklyn-api</artifactId>
<version>${project.version}</version>
</dependency>
@@ -121,6 +126,13 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.brooklyn</groupId>
+ <artifactId>brooklyn-software-cm-chef</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
<!-- bring in jclouds for testing -->
<dependency>
<groupId>org.apache.brooklyn</groupId>