From d113c7f856c1c3a9855d1fb71c5188234fba3561 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Fri, 15 Sep 2017 21:00:28 +0100 Subject: [PATCH] Move chef to own module in brooklyn-library --- .../entity/chef/ChefAttributeFeed.java | 413 ------------------ .../entity/chef/ChefAttributePollConfig.java | 61 --- .../entity/chef/ChefBashCommands.java | 42 -- .../brooklyn/entity/chef/ChefConfig.java | 94 ---- .../brooklyn/entity/chef/ChefConfigs.java | 102 ----- .../brooklyn/entity/chef/ChefEntity.java | 26 -- .../brooklyn/entity/chef/ChefEntityImpl.java | 39 -- .../chef/ChefLifecycleEffectorTasks.java | 364 --------------- .../brooklyn/entity/chef/ChefServerTasks.java | 97 ---- .../brooklyn/entity/chef/ChefSoloDriver.java | 85 ---- .../brooklyn/entity/chef/ChefSoloTasks.java | 70 --- .../brooklyn/entity/chef/ChefTasks.java | 154 ------- .../entity/chef/KnifeConvergeTaskFactory.java | 249 ----------- .../entity/chef/KnifeTaskFactory.java | 241 ---------- .../resolve/ChefEntitySpecResolver.java | 42 -- ...lyn.core.resolve.entity.EntitySpecResolver | 1 - .../OSGI-INF/blueprint/blueprint.xml | 5 - software/base/src/main/resources/catalog.bom | 4 - .../brooklyn/entity/chef/ChefConfigsTest.java | 40 -- .../entity/chef/ChefLiveTestSupport.java | 99 ----- .../chef/ChefServerTasksIntegrationTest.java | 109 ----- .../AbstractChefToyMySqlEntityLiveTest.java | 41 -- .../ChefSoloDriverMySqlEntityLiveTest.java | 49 --- .../mysql/ChefSoloDriverToyMySqlEntity.java | 89 ---- ...cChefAutodetectToyMySqlEntityLiveTest.java | 43 -- ...namicChefServerToyMySqlEntityLiveTest.java | 50 --- ...DynamicChefSoloToyMySqlEntityLiveTest.java | 43 -- .../chef/mysql/DynamicToyMySqlEntityChef.java | 81 ---- .../chef/mysql/TypedToyMySqlEntityChef.java | 55 --- 29 files changed, 2788 deletions(-) delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributeFeed.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributePollConfig.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefBashCommands.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfig.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfigs.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntity.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntityImpl.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefServerTasks.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloDriver.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloTasks.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefTasks.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java delete mode 100644 software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefConfigsTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java delete mode 100644 software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributeFeed.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributeFeed.java deleted file mode 100644 index f6d2615d05..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributeFeed.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * 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.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.mgmt.ExecutionContext; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.feed.AbstractFeed; -import org.apache.brooklyn.core.feed.PollHandler; -import org.apache.brooklyn.core.feed.Poller; -import org.apache.brooklyn.feed.ssh.SshPollValue; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.time.Duration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.google.common.base.Splitter; -import com.google.common.base.Strings; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -/** - * A sensor feed that retrieves attributes from Chef server and converts selected attributes to sensors. - * - *

To use this feed, you must provide the entity, the name of the node as it is known to Chef, and a collection of attribute - * sensors. The attribute sensors must follow the naming convention of starting with the string chef.attribute. - * followed by a period-separated path through the Chef attribute hierarchy. For example, an attribute sensor named - * chef.attribute.sql_server.instance_name would cause the feed to search for a Chef attribute called - * sql_server, and within that an attribute instance_name, and set the sensor to the value of this - * attribute.

- * - *

This feed uses the knife tool to query all the attributes on a named node. It then iterates over the configured - * list of attribute sensors, using the sensor name to locate an equivalent Chef attribute. The sensor is then set to the value - * of the Chef attribute.

- * - *

Example:

- * - * {@code - * @Override - * protected void connectSensors() { - * nodeAttributesFeed = ChefAttributeFeed.newFeed(this, nodeName, new AttributeSensor[]{ - * SqlServerNode.CHEF_ATTRIBUTE_NODE_NAME, - * SqlServerNode.CHEF_ATTRIBUTE_SQL_SERVER_INSTANCE_NAME, - * SqlServerNode.CHEF_ATTRIBUTE_SQL_SERVER_PORT, - * SqlServerNode.CHEF_ATTRIBUTE_SQL_SERVER_SA_PASSWORD - * }); - * } - * } - * - * @since 0.6.0 - * @author richardcloudsoft - */ -public class ChefAttributeFeed extends AbstractFeed { - - private static final Logger log = LoggerFactory.getLogger(ChefAttributeFeed.class); - - /** - * Prefix for attribute sensor names. - */ - public static final String CHEF_ATTRIBUTE_PREFIX = "chef.attribute."; - - @SuppressWarnings("serial") - public static final ConfigKey>> POLLS = ConfigKeys.newConfigKey( - new TypeToken>>() {}, - "polls"); - - public static final ConfigKey NODE_NAME = ConfigKeys.newStringConfigKey("nodeName"); - - public static Builder builder() { - return new Builder(); - } - - @SuppressWarnings("rawtypes") - public static class Builder { - private Entity entity; - private boolean onlyIfServiceUp = false; - private String nodeName; - private Set polls = Sets.newLinkedHashSet(); - private Duration period = Duration.of(30, TimeUnit.SECONDS); - private String uniqueTag; - private volatile boolean built; - - public Builder entity(Entity val) { - this.entity = checkNotNull(val, "entity"); - return this; - } - public Builder onlyIfServiceUp() { return onlyIfServiceUp(true); } - public Builder onlyIfServiceUp(boolean onlyIfServiceUp) { - this.onlyIfServiceUp = onlyIfServiceUp; - return this; - } - public Builder nodeName(String nodeName) { - this.nodeName = checkNotNull(nodeName, "nodeName"); - return this; - } - public Builder addSensor(ChefAttributePollConfig config) { - polls.add(config); - return this; - } - @SuppressWarnings("unchecked") - public Builder addSensor(String chefAttributePath, AttributeSensor sensor) { - return addSensor(new ChefAttributePollConfig(sensor).chefAttributePath(chefAttributePath)); - } - public Builder addSensors(Map sensors) { - for (Map.Entry entry : sensors.entrySet()) { - addSensor(entry.getKey(), entry.getValue()); - } - return this; - } - public Builder addSensors(AttributeSensor[] sensors) { - return addSensors(Arrays.asList(checkNotNull(sensors, "sensors"))); - } - public Builder addSensors(Iterable sensors) { - for(AttributeSensor sensor : checkNotNull(sensors, "sensors")) { - checkNotNull(sensor, "sensors collection contains a null value"); - checkArgument(sensor.getName().startsWith(CHEF_ATTRIBUTE_PREFIX), "sensor name must be prefixed "+CHEF_ATTRIBUTE_PREFIX+" for autodetection to work"); - addSensor(sensor.getName().substring(CHEF_ATTRIBUTE_PREFIX.length()), sensor); - } - return this; - } - public Builder period(Duration period) { - this.period = period; - return this; - } - public Builder period(long millis) { - return period(Duration.of(millis, TimeUnit.MILLISECONDS)); - } - public Builder period(long val, TimeUnit units) { - return period(Duration.of(val, units)); - } - public Builder uniqueTag(String uniqueTag) { - this.uniqueTag = uniqueTag; - return this; - } - public ChefAttributeFeed build() { - built = true; - ChefAttributeFeed result = new ChefAttributeFeed(this); - result.setEntity(checkNotNull((EntityLocal)entity, "entity")); - result.start(); - return result; - } - @Override - protected void finalize() { - if (!built) log.warn("SshFeed.Builder created, but build() never called"); - } - } - - private KnifeTaskFactory knifeTaskFactory; - - /** - * For rebind; do not call directly; use builder - */ - public ChefAttributeFeed() { - } - - protected ChefAttributeFeed(Builder builder) { - setConfig(ONLY_IF_SERVICE_UP, builder.onlyIfServiceUp); - setConfig(NODE_NAME, checkNotNull(builder.nodeName, "builder.nodeName")); - - Set> polls = Sets.newLinkedHashSet(); - for (ChefAttributePollConfig config : builder.polls) { - if (!config.isEnabled()) continue; - @SuppressWarnings({ "unchecked", "rawtypes" }) - ChefAttributePollConfig configCopy = new ChefAttributePollConfig(config); - if (configCopy.getPeriod() < 0) configCopy.period(builder.period); - polls.add(configCopy); - } - setConfig(POLLS, polls); - initUniqueTag(builder.uniqueTag, polls); - } - - @Override - protected void preStart() { - final String nodeName = getConfig(NODE_NAME); - final Set> polls = getConfig(POLLS); - - long minPeriod = Integer.MAX_VALUE; - for (ChefAttributePollConfig config : polls) { - minPeriod = Math.min(minPeriod, config.getPeriod()); - } - - knifeTaskFactory = new KnifeNodeAttributeQueryTaskFactory(nodeName); - - final Callable getAttributesFromKnife = new Callable() { - @Override - public SshPollValue call() throws Exception { - ProcessTaskWrapper taskWrapper = knifeTaskFactory.newTask(); - final ExecutionContext executionContext = ((EntityInternal) entity).getExecutionContext(); - log.debug("START: Running knife to query attributes of Chef node {}", nodeName); - executionContext.submit(taskWrapper); - taskWrapper.block(); - log.debug("DONE: Running knife to query attributes of Chef node {}", nodeName); - return new SshPollValue(null, taskWrapper.getExitCode(), taskWrapper.getStdout(), taskWrapper.getStderr()); - } - }; - - getPoller().scheduleAtFixedRate( - new CallInEntityExecutionContext(entity, getAttributesFromKnife), - new SendChefAttributesToSensors(entity, polls), - minPeriod); - } - - @Override - @SuppressWarnings("unchecked") - protected Poller getPoller() { - return (Poller) super.getPoller(); - } - - /** - * An implementation of {@link KnifeTaskFactory} that queries for the attributes of a node. - */ - private static class KnifeNodeAttributeQueryTaskFactory extends KnifeTaskFactory { - private final String nodeName; - - public KnifeNodeAttributeQueryTaskFactory(String nodeName) { - super("retrieve attributes of node " + nodeName); - this.nodeName = nodeName; - } - - @Override - protected List initialKnifeParameters() { - return ImmutableList.of("node", "show", "-l", nodeName, "--format", "json"); - } - } - - /** - * A {@link Callable} that wraps another {@link Callable}, where the inner {@link Callable} is executed in the context of a - * specific entity. - * - * @param The type of the {@link Callable}. - */ - private static class CallInEntityExecutionContext implements Callable { - - private final Callable job; - private Entity entity; - - private CallInEntityExecutionContext(Entity entity, Callable job) { - this.job = job; - this.entity = entity; - } - - @Override - public T call() throws Exception { - final ExecutionContext executionContext = ((EntityInternal) entity).getExecutionContext(); - return executionContext.submit(Maps.newHashMap(), job).get(); - } - } - - /** - * A poll handler that takes the result of the knife invocation and sets the appropriate sensors. - */ - private static class SendChefAttributesToSensors implements PollHandler { - private static final Iterable PREFIXES = ImmutableList.of("", "automatic", "force_override", "override", "normal", "force_default", "default"); - private static final Splitter SPLITTER = Splitter.on('.'); - - private final Entity entity; - private final Map> chefAttributeSensors; - - public SendChefAttributesToSensors(Entity entity, Set> polls) { - this.entity = entity; - chefAttributeSensors = Maps.newLinkedHashMap(); - for (ChefAttributePollConfig config : polls) { - chefAttributeSensors.put(config.getChefAttributePath(), config.getSensor()); - } - } - - @Override - public boolean checkSuccess(SshPollValue val) { - if (val.getExitStatus() != 0) return false; - String stderr = val.getStderr(); - if (stderr == null || stderr.length() != 0) return false; - String out = val.getStdout(); - if (out == null || out.length() == 0) return false; - if (!out.contains("{")) return false; - return true; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public void onSuccess(SshPollValue val) { - String stdout = val.getStdout(); - int jsonStarts = stdout.indexOf('{'); - if (jsonStarts > 0) - stdout = stdout.substring(jsonStarts); - JsonElement jsonElement = new Gson().fromJson(stdout, JsonElement.class); - - for (Map.Entry> attribute : chefAttributeSensors.entrySet()) { - String chefAttributeName = attribute.getKey(); - AttributeSensor sensor = attribute.getValue(); - log.trace("Finding value for attribute sensor " + sensor.getName()); - - Iterable path = SPLITTER.split(chefAttributeName); - JsonElement elementForSensor = null; - for(String prefix : PREFIXES) { - Iterable prefixedPath = !Strings.isNullOrEmpty(prefix) - ? Iterables.concat(ImmutableList.of(prefix), path) - : path; - try { - elementForSensor = getElementByPath(jsonElement.getAsJsonObject(), prefixedPath); - } catch(IllegalArgumentException e) { - log.error("Entity {}: bad Chef attribute {} for sensor {}: {}", new Object[]{ - entity.getDisplayName(), - Joiner.on('.').join(prefixedPath), - sensor.getName(), - e.getMessage()}); - throw Throwables.propagate(e); - } - if (elementForSensor != null) { - log.debug("Entity {}: apply Chef attribute {} to sensor {} with value {}", new Object[]{ - entity.getDisplayName(), - Joiner.on('.').join(prefixedPath), - sensor.getName(), - elementForSensor.getAsString()}); - break; - } - } - if (elementForSensor != null) { - entity.sensors().set((AttributeSensor)sensor, TypeCoercions.coerce(elementForSensor.getAsString(), sensor.getTypeToken())); - } else { - log.debug("Entity {}: no Chef attribute matching {}; setting sensor {} to null", new Object[]{ - entity.getDisplayName(), - chefAttributeName, - sensor.getName()}); - entity.sensors().set(sensor, null); - } - } - } - - private JsonElement getElementByPath(JsonElement element, Iterable path) { - if (Iterables.isEmpty(path)) { - return element; - } else { - String head = Iterables.getFirst(path, null); - Preconditions.checkArgument(!Strings.isNullOrEmpty(head), "path must not contain empty or null elements"); - Iterable tail = Iterables.skip(path, 1); - JsonElement child = ((JsonObject) element).get(head); - return child != null - ? getElementByPath(child, tail) - : null; - } - } - - @Override - public void onFailure(SshPollValue val) { - log.error("Chef attribute query did not respond as expected. exitcode={} stdout={} stderr={}", new Object[]{val.getExitStatus(), val.getStdout(), val.getStderr()}); - for (AttributeSensor attribute : chefAttributeSensors.values()) { - if (!attribute.getName().startsWith(CHEF_ATTRIBUTE_PREFIX)) - continue; - entity.sensors().set(attribute, null); - } - } - - @Override - public void onException(Exception exception) { - log.error("Detected exception while retrieving Chef attributes from entity " + entity.getDisplayName(), exception); - for (AttributeSensor attribute : chefAttributeSensors.values()) { - if (!attribute.getName().startsWith(CHEF_ATTRIBUTE_PREFIX)) - continue; - entity.sensors().set(attribute, null); - } - } - - @Override - public String toString() { - return super.toString()+"["+getDescription()+"]"; - } - - @Override - public String getDescription() { - return ""+chefAttributeSensors; - } - } -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributePollConfig.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributePollConfig.java deleted file mode 100644 index c090f34681..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributePollConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.google.common.base.Function; -import com.google.common.base.Functions; - -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.core.feed.PollConfig; - -public class ChefAttributePollConfig extends PollConfig>{ - - private String chefAttributePath; - - public static ChefAttributePollConfig forSensor(AttributeSensor sensor) { - return new ChefAttributePollConfig(sensor); - } - - public static ChefAttributePollConfig forMultiple() { - return new ChefAttributePollConfig(PollConfig.NO_SENSOR); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public ChefAttributePollConfig(AttributeSensor sensor) { - super(sensor); - onSuccess((Function)Functions.identity()); - } - - public ChefAttributePollConfig(ChefAttributePollConfig other) { - super(other); - this.chefAttributePath = other.chefAttributePath; - } - - public String getChefAttributePath() { - return chefAttributePath; - } - - public ChefAttributePollConfig chefAttributePath(String val) { - this.chefAttributePath = val; return this; - } - - @Override protected String toStringBaseName() { return "chef"; } - @Override protected String toStringPollSource() { return chefAttributePath; } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefBashCommands.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefBashCommands.java deleted file mode 100644 index dde58d37af..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefBashCommands.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 org.apache.brooklyn.util.ssh.BashCommands.INSTALL_CURL; -import static org.apache.brooklyn.util.ssh.BashCommands.INSTALL_TAR; -import static org.apache.brooklyn.util.ssh.BashCommands.INSTALL_UNZIP; -import static org.apache.brooklyn.util.ssh.BashCommands.downloadToStdout; -import static org.apache.brooklyn.util.ssh.BashCommands.sudo; - -import org.apache.brooklyn.util.ssh.BashCommands; - -import com.google.common.annotations.Beta; - -/** BASH commands useful for setting up Chef */ -@Beta -public class ChefBashCommands { - - public static final String INSTALL_FROM_OPSCODE = - BashCommands.chain( - INSTALL_CURL, - INSTALL_TAR, - INSTALL_UNZIP, - "( "+downloadToStdout("https://www.opscode.com/chef/install.sh") + " | " + sudo("bash")+" )"); - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfig.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfig.java deleted file mode 100644 index 07b4ce5105..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfig.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.config.MapConfigKey; -import org.apache.brooklyn.core.config.SetConfigKey; -import org.apache.brooklyn.util.core.flags.SetFromFlag; - -import com.google.common.annotations.Beta; - -/** {@link ConfigKey}s used to configure the chef driver */ -@Beta -public interface ChefConfig { - - public static final ConfigKey CHEF_COOKBOOK_PRIMARY_NAME = ConfigKeys.newStringConfigKey("brooklyn.chef.cookbook.primary.name", - "Namespace to use for passing data to Chef and for finding effectors"); - - @SetFromFlag("cookbook_urls") - public static final MapConfigKey CHEF_COOKBOOK_URLS = new MapConfigKey(String.class, "brooklyn.chef.cookbooksUrls"); - - @SetFromFlag("converge_twice") - public static final ConfigKey CHEF_RUN_CONVERGE_TWICE = ConfigKeys.newBooleanConfigKey("brooklyn.chef.converge.twice", - "Whether to run converge commands twice if the first one fails; needed in some contexts, e.g. when switching between chef-server and chef-solo mode", false); - - @Deprecated /** @deprecated since 0.7.0 use #CHEF_LAUNCH_RUN_LIST */ - public static final SetConfigKey CHEF_RUN_LIST = new SetConfigKey(String.class, "brooklyn.chef.runList"); - - /** typically set from spec, to customize the launch part of the start effector */ - @SetFromFlag("launch_run_list") - public static final SetConfigKey CHEF_LAUNCH_RUN_LIST = new SetConfigKey(String.class, "brooklyn.chef.launch.runList"); - /** typically set from spec, to customize the launch part of the start effector */ - @SetFromFlag("launch_attributes") - public static final MapConfigKey CHEF_LAUNCH_ATTRIBUTES = new MapConfigKey(Object.class, "brooklyn.chef.launch.attributes"); - - public static enum ChefModes { - /** Force use of Chef Solo */ - SOLO, - /** Force use of Knife; knife must be installed, and either - * {@link ChefConfig#KNIFE_EXECUTABLE} and {@link ChefConfig#KNIFE_CONFIG_FILE} must be set - * or knife on the path with valid global config set up */ - KNIFE, - // TODO server via API - /** Tries {@link #KNIFE} if valid, else {@link #SOLO} */ - AUTODETECT - }; - - @SetFromFlag("chef_mode") - public static final ConfigKey CHEF_MODE = ConfigKeys.newConfigKey(ChefModes.class, "brooklyn.chef.mode", - "Whether Chef should run in solo mode, knife mode, or auto-detect", ChefModes.AUTODETECT); - - // TODO server-url for server via API mode - - public static final ConfigKey KNIFE_SETUP_COMMANDS = ConfigKeys.newStringConfigKey("brooklyn.chef.knife.setupCommands", - "An optional set of commands to run on localhost before invoking knife; useful if using ruby version manager for example"); - public static final ConfigKey KNIFE_EXECUTABLE = ConfigKeys.newStringConfigKey("brooklyn.chef.knife.executableFile", - "Knife command to run on the Brooklyn machine, including full path; defaults to scanning the path"); - public static final ConfigKey KNIFE_CONFIG_FILE = ConfigKeys.newStringConfigKey("brooklyn.chef.knife.configFile", - "Knife config file (typically knife.rb) to use, including full path; defaults to knife default/global config"); - - @SetFromFlag("chef_node_name") - public static final ConfigKey CHEF_NODE_NAME = ConfigKeys.newStringConfigKey("brooklyn.chef.node.nodeName", - "Node name to register with the chef server for this entity, if using Chef server and a specific node name is desired; " - + "if supplied ,this must be unique across the nodes Chef Server manages; if not supplied, one will be created if needed"); - - // for providing some simple (ssh-based) lifecycle operations and checks - @SetFromFlag("pid_file") - public static final ConfigKey PID_FILE = ConfigKeys.newStringConfigKey("brooklyn.chef.lifecycle.pidFile", - "Path to PID file on remote machine, for use in checking running and stopping; may contain wildcards"); - @SetFromFlag("service_name") - public static final ConfigKey SERVICE_NAME = ConfigKeys.newStringConfigKey("brooklyn.chef.lifecycle.serviceName", - "Name of OS service this will run as, for use in checking running and stopping"); - @SetFromFlag("windows_service_name") - public static final ConfigKey WINDOWS_SERVICE_NAME = ConfigKeys.newStringConfigKey("brooklyn.chef.lifecycle.windowsServiceName", - "Name of OS service this will run as on Windows, if different there, for use in checking running and stopping"); - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfigs.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfigs.java deleted file mode 100644 index 16d5fa00b6..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfigs.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.Map; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.MapConfigKey.MapModifications; -import org.apache.brooklyn.core.config.SetConfigKey.SetModifications; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.util.git.GithubUrls; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; - -/** Conveniences for configuring brooklyn Chef entities - * @since 0.6.0 */ -@Beta -public class ChefConfigs { - - public static void addToLaunchRunList(EntitySpec entity, String ...recipes) { - for (String recipe: recipes) - entity.configure(ChefConfig.CHEF_LAUNCH_RUN_LIST, SetModifications.addItem(recipe)); - } - - public static void addToLaunchRunList(EntityInternal entity, String ...recipes) { - for (String recipe: recipes) - entity.config().set(ChefConfig.CHEF_LAUNCH_RUN_LIST, SetModifications.addItem(recipe)); - } - - public static void addToCookbooksFromGithub(EntitySpec entity, String ...cookbookNames) { - for (String cookbookName: cookbookNames) - addToCookbooksFromGithub(entity, cookbookName, getGithubOpscodeRepo(cookbookName)); - } - - public static void addToCookbooksFromGithub(EntityInternal entity, String ...cookbookNames) { - for (String cookbookName: cookbookNames) - addToCookbooksFromGithub(entity, cookbookName, getGithubOpscodeRepo(cookbookName)); - } - - public static String getGithubOpscodeRepo(String cookbookName) { - return getGithubOpscodeRepo(cookbookName, "master"); - } - public static String getGithubOpscodeRepo(String cookbookName, String tag) { - return GithubUrls.tgz("opscode-cookbooks", cookbookName, tag); - } - - public static void addToCookbooksFromGithub(EntitySpec entity, String cookbookName, String cookbookUrl) { - entity.configure(ChefConfig.CHEF_COOKBOOK_URLS.subKey(cookbookName), cookbookUrl); - } - - public static void addToCookbooksFromGithub(EntityInternal entity, String cookbookName, String cookbookUrl) { - entity.config().set(ChefConfig.CHEF_COOKBOOK_URLS.subKey(cookbookName), cookbookUrl); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static void addLaunchAttributes(EntitySpec entity, Map attributesMap) { - entity.configure(ChefConfig.CHEF_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap)); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static void addLaunchAttributes(EntityInternal entity, Map attributesMap) { - entity.config().set(ChefConfig.CHEF_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap)); - } - - /** replaces the attributes underneath the rootAttribute parameter with the given value; - * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */ - public static void setLaunchAttribute(EntitySpec entity, String rootAttribute, Object value) { - entity.configure(ChefConfig.CHEF_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value); - } - - /** replaces the attributes underneath the rootAttribute parameter with the given value; - * see {@link #addLaunchAttributesMap(EntitySpec, Map)} for richer functionality */ - public static void setLaunchAttribute(EntityInternal entity, String rootAttribute, Object value) { - entity.config().set(ChefConfig.CHEF_LAUNCH_ATTRIBUTES.subKey(rootAttribute), value); - } - - public static T getRequiredConfig(Entity entity, ConfigKey key) { - return Preconditions.checkNotNull( - Preconditions.checkNotNull(entity, "Entity must be supplied").getConfig(key), - "Key "+key+" is required on "+entity); - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntity.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntity.java deleted file mode 100644 index 1b1f866455..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntity.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 org.apache.brooklyn.api.entity.ImplementedBy; -import org.apache.brooklyn.entity.software.base.SoftwareProcess; - -@ImplementedBy(ChefEntityImpl.class) -public interface ChefEntity extends SoftwareProcess, ChefConfig { -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntityImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntityImpl.java deleted file mode 100644 index 6bc3cfd7b4..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntityImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 org.apache.brooklyn.entity.stock.EffectorStartableImpl; -import org.apache.brooklyn.util.text.Strings; - -public class ChefEntityImpl extends EffectorStartableImpl implements ChefEntity { - - @Override - public void init() { - String primaryName = getConfig(CHEF_COOKBOOK_PRIMARY_NAME); - if (!Strings.isBlank(primaryName)) setDefaultDisplayName(primaryName+" (chef)"); - - super.init(); - new ChefLifecycleEffectorTasks().attachLifecycleEffectors(this); - } - - @Override - public void populateServiceNotUpDiagnostics() { - // TODO no-op currently; should check ssh'able etc - } -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java deleted file mode 100644 index 8c3dad960a..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * 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.Collection; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.location.MachineLocation; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; -import org.apache.brooklyn.core.entity.Attributes; -import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; -import org.apache.brooklyn.core.location.Machines; -import org.apache.brooklyn.entity.software.base.SoftwareProcess; -import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffectorTasks; -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.util.collections.Jsonya; -import org.apache.brooklyn.util.collections.Jsonya.Navigator; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.TaskTags; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.net.Urls; -import org.apache.brooklyn.util.ssh.BashCommands; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.time.Duration; -import org.apache.brooklyn.util.time.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; - -/** - * Creates effectors to start, restart, and stop processes using Chef. - *

- * Instances of this should use the {@link ChefConfig} config attributes to configure startup, - * and invoke {@link #usePidFile(String)} or {@link #useService(String)} to determine check-running and stop behaviour. - * Alternatively this can be subclassed and {@link #postStartCustom()} and {@link #stopProcessesAtMachine()} overridden. - * - * @since 0.6.0 - **/ -@Beta -public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements ChefConfig { - - private static final Logger log = LoggerFactory.getLogger(ChefLifecycleEffectorTasks.class); - - protected String _pidFile, _serviceName, _windowsServiceName; - - public ChefLifecycleEffectorTasks() { - } - - public ChefLifecycleEffectorTasks usePidFile(String pidFile) { - this._pidFile = pidFile; - return this; - } - public ChefLifecycleEffectorTasks useService(String serviceName) { - this._serviceName = serviceName; - return this; - } - public ChefLifecycleEffectorTasks useWindowsService(String serviceName) { - this._windowsServiceName = serviceName; - return this; - } - - public String getPidFile() { - if (_pidFile!=null) return _pidFile; - return _pidFile = entity().getConfig(ChefConfig.PID_FILE); - } - - public String getServiceName() { - if (_serviceName!=null) return _serviceName; - return _serviceName = entity().getConfig(ChefConfig.SERVICE_NAME); - } - - protected String getNodeName() { - // (node name is needed so we can node delete it) - - // TODO would be better if CHEF_NODE_NAME were a freemarker template, could access entity.id, or hostname, etc, - // in addition to supporting hard-coded node names (which is all we support so far). - - String nodeName = entity().getConfig(ChefConfig.CHEF_NODE_NAME); - if (Strings.isNonBlank(nodeName)) return Strings.makeValidFilename(nodeName); - // node name is taken from ID of this entity, if not specified - return entity().getId(); - } - - public String getWindowsServiceName() { - if (_windowsServiceName!=null) return _windowsServiceName; - return _windowsServiceName = entity().getConfig(ChefConfig.WINDOWS_SERVICE_NAME); - } - - @Override - public void attachLifecycleEffectors(Entity entity) { - if (getPidFile()==null && getServiceName()==null && getClass().equals(ChefLifecycleEffectorTasks.class)) { - // warn on incorrect usage - log.warn("Uses of "+getClass()+" must define a PID file or a service name (or subclass and override {start,stop} methods as per javadoc) " + - "in order for check-running and stop to work"); - } - - super.attachLifecycleEffectors(entity); - } - - public static ChefModes detectChefMode(Entity entity) { - ChefModes mode = entity.getConfig(ChefConfig.CHEF_MODE); - if (mode == ChefModes.AUTODETECT) { - // TODO server via API - ProcessTaskWrapper installCheck = DynamicTasks.queue( - ChefServerTasks.isKnifeInstalled()); - mode = installCheck.get() ? ChefModes.KNIFE : ChefModes.SOLO; - log.debug("Using Chef in "+mode+" mode due to autodetect exit code "+installCheck.getExitCode()); - } - Preconditions.checkNotNull(mode, "Non-null "+ChefConfig.CHEF_MODE+" required for "+entity); - return mode; - } - - @Override - protected String startProcessesAtMachine(Supplier machineS) { - ChefModes mode = detectChefMode(entity()); - switch (mode) { - case KNIFE: - startWithKnifeAsync(); - break; - - case SOLO: - startWithChefSoloAsync(); - break; - - default: - throw new IllegalStateException("Unknown Chef mode "+mode+" when starting processes for "+entity()); - } - - return "chef start tasks submitted ("+mode+")"; - } - - protected String getPrimaryCookbook() { - return entity().getConfig(CHEF_COOKBOOK_PRIMARY_NAME); - } - - @SuppressWarnings({ "unchecked", "deprecation" }) - protected void startWithChefSoloAsync() { - String baseDir = MachineLifecycleEffectorTasks.resolveOnBoxDir(entity(), Machines.findUniqueMachineLocation(entity().getLocations(), SshMachineLocation.class).get()); - String installDir = Urls.mergePaths(baseDir, "installs/chef"); - - @SuppressWarnings("rawtypes") - Map cookbooks = (Map) - ConfigBag.newInstance( entity().getConfig(CHEF_COOKBOOK_URLS) ) - .putIfAbsent( entity().getConfig(CHEF_COOKBOOK_URLS) ) - .getAllConfig(); - if (cookbooks.isEmpty()) - log.warn("No cookbook_urls set for "+entity()+"; launch will likely fail subsequently"); - DynamicTasks.queue( - ChefSoloTasks.installChef(installDir, false), - ChefSoloTasks.installCookbooks(installDir, cookbooks, false)); - - // TODO chef for and run a prestart recipe if necessary - // TODO open ports - - String primary = getPrimaryCookbook(); - - // put all config under brooklyn/cookbook/config - Navigator> attrs = Jsonya.newInstancePrimitive().at("brooklyn"); - if (Strings.isNonBlank(primary)) attrs.at(primary); - attrs.at("config"); - attrs.put( entity().config().getBag().getAllConfig() ); - // and put launch attrs at root - try { - attrs.root().put((Map)Tasks.resolveDeepValue(entity().getConfig(CHEF_LAUNCH_ATTRIBUTES), Object.class, entity().getExecutionContext())); - } catch (Exception e) { Exceptions.propagate(e); } - - Collection runList = entity().getConfig(CHEF_LAUNCH_RUN_LIST); - if (runList==null) runList = entity().getConfig(CHEF_RUN_LIST); - if (runList==null) { - if (Strings.isNonBlank(primary)) runList = ImmutableList.of(primary+"::"+"start"); - else throw new IllegalStateException("Require a primary cookbook or a run_list to effect "+"start"+" on "+entity()); - } - - String runDir = Urls.mergePaths(baseDir, - "apps/"+entity().getApplicationId()+"/chef/entities/"+entity().getEntityType().getSimpleName()+"_"+entity().getId()); - - DynamicTasks.queue(ChefSoloTasks.buildChefFile(runDir, installDir, "launch", - runList, (Map) attrs.root().get())); - - DynamicTasks.queue(ChefSoloTasks.runChef(runDir, "launch", entity().getConfig(CHEF_RUN_CONVERGE_TWICE))); - } - - @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" }) - protected void startWithKnifeAsync() { - // TODO prestart, ports (as above); also, note, some aspects of this are untested as we need a chef server - - String primary = getPrimaryCookbook(); - - // put all config under brooklyn/cookbook/config - Navigator> attrs = Jsonya.newInstancePrimitive().at("brooklyn"); - if (Strings.isNonBlank(primary)) attrs.at(primary); - attrs.at("config"); - attrs.put( entity().config().getBag().getAllConfig() ); - // and put launch attrs at root - try { - attrs.root().put((Map)Tasks.resolveDeepValue(entity().getConfig(CHEF_LAUNCH_ATTRIBUTES), Object.class, entity().getExecutionContext())); - } catch (Exception e) { Exceptions.propagate(e); } - - Collection runList = entity().getConfig(CHEF_LAUNCH_RUN_LIST); - if (runList==null) runList = entity().getConfig(CHEF_RUN_LIST); - if (runList==null) { - if (Strings.isNonBlank(primary)) runList = ImmutableList.of(primary+"::"+"start"); - else throw new IllegalStateException("Require a primary cookbook or a run_list to effect "+"start"+" on "+entity()); - } - - DynamicTasks.queue( - ChefServerTasks.knifeConvergeTask() - .knifeNodeName(getNodeName()) - .knifeRunList(Strings.join(runList, ",")) - .knifeAddAttributes((Map) attrs.root().get()) - .knifeRunTwice(entity().getConfig(CHEF_RUN_CONVERGE_TWICE)) ); - } - - @Override - protected void postStartCustom() { - boolean result = false; - result |= tryCheckStartPid(); - result |= tryCheckStartService(); - result |= tryCheckStartWindowsService(); - if (!result) { - log.warn("No way to check whether "+entity()+" is running; assuming yes"); - } - entity().sensors().set(SoftwareProcess.SERVICE_UP, true); - super.postStartCustom(); - } - - protected boolean tryCheckStartPid() { - if (getPidFile()==null) return false; - - // if it's still up after 5s assume we are good (default behaviour) - Time.sleep(Duration.FIVE_SECONDS); - if (!DynamicTasks.queue(SshEffectorTasks.isPidFromFileRunning(getPidFile()).runAsRoot()).get()) { - throw new IllegalStateException("The process for "+entity()+" appears not to be running (pid file "+getPidFile()+")"); - } - - // and set the PID - entity().sensors().set(Attributes.PID, - Integer.parseInt(DynamicTasks.queue(SshEffectorTasks.ssh("cat "+getPidFile()).runAsRoot()).block().getStdout().trim())); - return true; - } - - protected boolean tryCheckStartService() { - if (getServiceName()==null) return false; - - // if it's still up after 5s assume we are good (default behaviour) - Time.sleep(Duration.FIVE_SECONDS); - if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+getServiceName()+" status").runAsRoot()).get())) { - throw new IllegalStateException("The process for "+entity()+" appears not to be running (service "+getServiceName()+")"); - } - - return true; - } - - protected boolean tryCheckStartWindowsService() { - if (getWindowsServiceName()==null) return false; - - // if it's still up after 5s assume we are good (default behaviour) - Time.sleep(Duration.FIVE_SECONDS); - if (!((Integer)0).equals(DynamicTasks.queue(SshEffectorTasks.ssh("sc query \""+getWindowsServiceName()+"\" | find \"RUNNING\"").runAsCommand()).get())) { - throw new IllegalStateException("The process for "+entity()+" appears not to be running (windowsService "+getWindowsServiceName()+")"); - } - - return true; - } - - @Override - protected String stopProcessesAtMachine() { - boolean result = false; - result |= tryStopService(); - result |= tryStopWindowsService(); - result |= tryStopPid(); - if (!result) { - throw new IllegalStateException("The process for "+entity()+" could not be stopped (no impl!)"); - } - return "stopped"; - } - - @Override - protected StopMachineDetails stopAnyProvisionedMachines() { - if (detectChefMode(entity())==ChefModes.KNIFE) { - DynamicTasks.queue( - // if this task fails show it as failed but don't block subsequent routines - // (ie allow us to actually decommission the machine) - // TODO args could be a List config key ? - TaskTags.markInessential( - new KnifeTaskFactory("delete node and client registration at chef server") - .add("knife node delete "+getNodeName()+" -y") - .add("knife client delete "+getNodeName()+" -y") - .requiringZeroAndReturningStdout() - .newTask() )); - } - - return super.stopAnyProvisionedMachines(); - } - - protected boolean tryStopService() { - if (getServiceName()==null) return false; - int result = DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+getServiceName()+" stop").runAsRoot()).get(); - if (0==result) return true; - if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)!=Lifecycle.RUNNING) - return true; - - throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)"); - } - - protected boolean tryStopWindowsService() { - if (getWindowsServiceName()==null) return false; - int result = DynamicTasks.queue(SshEffectorTasks.ssh("sc query \""+getWindowsServiceName()+"\"").runAsCommand()).get(); - if (0==result) return true; - if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)!=Lifecycle.RUNNING) - return true; - - throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)"); - } - - protected boolean tryStopPid() { - Integer pid = entity().getAttribute(Attributes.PID); - if (pid==null) { - if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)==Lifecycle.RUNNING && getPidFile()==null) - log.warn("No PID recorded for "+entity()+" when running, with PID file "+getPidFile()+"; skipping kill in "+Tasks.current()); - else - if (log.isDebugEnabled()) - log.debug("No PID recorded for "+entity()+"; skipping ("+entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)+" / "+getPidFile()+")"); - return false; - } - - // allow non-zero exit as process may have already been killed - DynamicTasks.queue(SshEffectorTasks.ssh( - "kill "+pid, "sleep 5", BashCommands.ok("kill -9 "+pid)).allowingNonZeroExitCode().runAsRoot()).block(); - - if (DynamicTasks.queue(SshEffectorTasks.isPidRunning(pid).runAsRoot()).get()) { - throw new IllegalStateException("Process for "+entity()+" in "+pid+" still running after kill"); - } - entity().sensors().set(Attributes.PID, null); - return true; - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefServerTasks.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefServerTasks.java deleted file mode 100644 index c81ff9defa..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefServerTasks.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.IOException; -import java.nio.charset.Charset; -import java.security.KeyPair; - -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.util.core.crypto.SecureKeys; - -import com.google.common.base.Throwables; -import com.google.common.io.Files; - -public class ChefServerTasks { - - private static File chefKeyDir; - - private synchronized static File getExtractedKeysDir() { - if (chefKeyDir==null) { - chefKeyDir = Files.createTempDir(); - chefKeyDir.deleteOnExit(); - } - return chefKeyDir; - } - - /** extract key to a temp file, but one per machine, scheduled for deletion afterwards; - * we extract the key because chef has no way to accept passphrases at present */ - synchronized static File extractKeyFile(SshMachineLocation machine) { - File f = new File(getExtractedKeysDir(), machine.getAddress().getHostName()+".pem"); - if (f.exists()) return f; - KeyPair data = machine.findKeyPair(); - if (data==null) return null; - try { - f.deleteOnExit(); - Files.write(SecureKeys.stringPem(data), f, Charset.defaultCharset()); - return f; - } catch (IOException e) { - throw Throwables.propagate(e); - } - } - - public static KnifeTaskFactory isKnifeInstalled() { - return new KnifeTaskFactory("knife install check") - .knifeAddParameters("node list") - .notThrowingOnCommonKnifeErrors() - .returningIsExitCodeZero(); - } - - /** plain knife converge task - run list must be set, other arguments are optional */ - public static KnifeConvergeTaskFactory knifeConvergeTask() { - return new KnifeConvergeTaskFactory("knife converge") - .requiringZeroAndReturningStdout(); - } - /** knife converge task configured for this run list (and sudo) */ - public static KnifeConvergeTaskFactory knifeConvergeRunList(String runList) { - return knifeConvergeTask() - .knifeRunList(runList) - .knifeSudo(true); - } - - /** knife converge task configured for this run list on windows (ssh) */ - public static KnifeConvergeTaskFactory knifeConvergeRunListWindowsSsh(String runList) { - return knifeConvergeTask() - .knifeRunList(runList) - .knifeSudo(false) - .knifeAddExtraBootstrapParameters("windows ssh"); - } - - /** knife converge task configured for this run list on windows (winrm) */ - public static KnifeConvergeTaskFactory knifeConvergeRunListWindowsWinrm(String runList) { - return knifeConvergeTask() - .knifeRunList(runList) - .knifeSudo(false) - .knifeAddExtraBootstrapParameters("windows winrm") - .knifePortUseKnifeDefault(); - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloDriver.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloDriver.java deleted file mode 100644 index 6ee178619a..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloDriver.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 org.apache.brooklyn.api.entity.EntityLocal; -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.entity.software.base.AbstractSoftwareProcessSshDriver; -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.util.core.task.DynamicTasks; - -import com.google.common.annotations.Beta; -import com.google.common.reflect.TypeToken; - -/** Driver class to facilitate use of Chef */ -@Beta -@Deprecated /** @deprecated since 0.7.0 use ChefEntity or ChefLifecycleEffectorTasks */ -public class ChefSoloDriver extends AbstractSoftwareProcessSshDriver implements ChefConfig { - - @SuppressWarnings("serial") - public static final ConfigKey>> IS_RUNNING_TASK = ConfigKeys.newConfigKey( - new TypeToken>>() {}, - "brooklyn.chef.task.driver.isRunningTask"); - - @SuppressWarnings("serial") - public static final ConfigKey> STOP_TASK = ConfigKeys.newConfigKey( - new TypeToken>() {}, - "brooklyn.chef.task.driver.stopTask"); - - public ChefSoloDriver(EntityLocal entity, SshMachineLocation location) { - super(entity, location); - } - - @Override - public void install() { - // TODO flag to force reinstallation - DynamicTasks.queue( - ChefSoloTasks.installChef(getInstallDir(), false), - ChefSoloTasks.installCookbooks(getInstallDir(), getRequiredConfig(CHEF_COOKBOOK_URLS), false)); - } - - @Override - public void customize() { - DynamicTasks.queue(ChefSoloTasks.buildChefFile(getRunDir(), getInstallDir(), "launch", getRequiredConfig(CHEF_RUN_LIST), - getEntity().getConfig(CHEF_LAUNCH_ATTRIBUTES))); - } - - @Override - public void launch() { - DynamicTasks.queue(ChefSoloTasks.runChef(getRunDir(), "launch", getEntity().getConfig(CHEF_RUN_CONVERGE_TWICE))); - } - - @Override - public boolean isRunning() { - return DynamicTasks.queue(getRequiredConfig(IS_RUNNING_TASK)).asTask().getUnchecked(); - } - - @Override - public void stop() { - DynamicTasks.queue(getRequiredConfig(STOP_TASK)); - } - - protected T getRequiredConfig(ConfigKey key) { - return ChefConfigs.getRequiredConfig(getEntity(), key); - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloTasks.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloTasks.java deleted file mode 100644 index 505f37eabc..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloTasks.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.Map; - -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; -import org.apache.brooklyn.util.ssh.BashCommands; - -import com.google.common.annotations.Beta; - -@Beta -public class ChefSoloTasks { - - public static TaskFactory installChef(String chefDirectory, boolean force) { - // TODO check on entity whether it is chef _server_ - String installCmd = cdAndRun(chefDirectory, ChefBashCommands.INSTALL_FROM_OPSCODE); - if (!force) installCmd = BashCommands.alternatives("which chef-solo", installCmd); - return SshEffectorTasks.ssh(installCmd).summary("install chef"); - } - - public static TaskFactory installCookbooks(final String chefDirectory, final Map cookbooksAndUrls, final boolean force) { - return ChefTasks.installCookbooks(chefDirectory, cookbooksAndUrls, force); - } - - public static TaskFactory installCookbook(String chefDirectory, String cookbookName, String cookbookArchiveUrl, boolean force) { - return ChefTasks.installCookbook(chefDirectory, cookbookName, cookbookArchiveUrl, force); - } - - protected static String cdAndRun(String targetDirectory, String command) { - return BashCommands.chain("mkdir -p "+targetDirectory, - "cd "+targetDirectory, - command); - } - - public static TaskFactory buildChefFile(String runDirectory, String chefDirectory, String phase, Iterable runList, - Map optionalAttributes) { - return ChefTasks.buildChefFile(runDirectory, chefDirectory, phase, runList, optionalAttributes); - } - - public static TaskFactory runChef(String runDir, String phase) { - return runChef(runDir, phase, false); - } - /** see {@link ChefConfig#CHEF_RUN_CONVERGE_TWICE} for background on why 'twice' is available */ - public static TaskFactory runChef(String runDir, String phase, Boolean twice) { - String cmd = "sudo chef-solo -c "+phase+".rb -j "+phase+".json -ldebug"; - if (twice!=null && twice) cmd = BashCommands.alternatives(cmd, cmd); - - return SshEffectorTasks.ssh(cdAndRun(runDir, cmd)). - summary("run chef for "+phase).requiringExitCodeZero(); - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefTasks.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefTasks.java deleted file mode 100644 index e2edcb2e5c..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefTasks.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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.Map; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.core.effector.EffectorTasks; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.file.ArchiveTasks; -import org.apache.brooklyn.util.core.file.ArchiveUtils.ArchiveType; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.TaskBuilder; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.net.Urls; -import org.apache.brooklyn.util.ssh.BashCommands; -import org.apache.brooklyn.util.text.Identifiers; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -@Beta -public class ChefTasks { - - private static final Logger log = LoggerFactory.getLogger(ChefTasks.class); - - public static TaskFactory installChef(String chefDirectory, boolean force) { - // TODO check on entity whether it is chef _server_ - String installCmd = cdAndRun(chefDirectory, ChefBashCommands.INSTALL_FROM_OPSCODE); - if (!force) installCmd = BashCommands.alternatives("which chef-solo", installCmd); - return SshEffectorTasks.ssh(installCmd).summary("install chef"); - } - - public static TaskFactory installCookbooks(final String chefDirectory, final Map cookbooksAndUrls, final boolean force) { - return Tasks.builder().displayName("install "+(cookbooksAndUrls==null ? "0" : cookbooksAndUrls.size())+" cookbook"+Strings.s(cookbooksAndUrls)).body( - new Runnable() { - @Override - public void run() { - Entity e = EffectorTasks.findEntity(); - if (cookbooksAndUrls==null) - throw new IllegalStateException("No cookbooks defined to install at "+e); - for (String cookbook: cookbooksAndUrls.keySet()) - DynamicTasks.queue(installCookbook(chefDirectory, cookbook, cookbooksAndUrls.get(cookbook), force)); - } - }).buildFactory(); - } - - public static TaskFactory installCookbook(final String chefDirectory, final String cookbookName, final String cookbookArchiveUrl, final boolean force) { - return new TaskFactory>() { - @Override - public TaskAdaptable newTask() { - TaskBuilder tb = Tasks.builder().displayName("install cookbook "+cookbookName); - - String cookbookDir = Urls.mergePaths(chefDirectory, cookbookName); - String privateTmpDirContainingUnpackedCookbook = - Urls.mergePaths(chefDirectory, "tmp-"+Strings.makeValidFilename(cookbookName)+"-"+Identifiers.makeRandomId(4)); - - // TODO - skip the install earlier if it exists and isn't forced -// if (!force) { -// // in builder.body, check -// // "ls "+cookbookDir -// // and stop if it's zero -// // remove reference to 'force' below -// } - - String destName = null; - if (ArchiveType.of(cookbookArchiveUrl)==ArchiveType.UNKNOWN) { - destName = cookbookName + ".tgz"; - log.debug("Assuming TGZ type for chef cookbook url "+cookbookArchiveUrl+"; it will be downloaded as "+destName); - } - tb.add(ArchiveTasks.deploy(null, null, cookbookArchiveUrl, EffectorTasks.findSshMachine(), privateTmpDirContainingUnpackedCookbook, - false, null, destName).newTask()); - - String installCmd = BashCommands.chain( - "cd "+privateTmpDirContainingUnpackedCookbook, - "COOKBOOK_EXPANDED_DIR=`ls`", - BashCommands.requireTest("`ls | wc -w` -eq 1", - "The deployed archive "+cookbookArchiveUrl+" must contain exactly one directory"), - "mv $COOKBOOK_EXPANDED_DIR '../"+cookbookName+"'", - "cd ..", - "rm -rf '"+privateTmpDirContainingUnpackedCookbook+"'"); - - installCmd = force ? BashCommands.alternatives("rm -rf "+cookbookDir, installCmd) : BashCommands.alternatives("ls "+cookbookDir+" > /dev/null 2> /dev/null", installCmd); - tb.add(SshEffectorTasks.ssh(installCmd).summary("renaming cookbook dir").requiringExitCodeZero().newTask()); - - return tb.build(); - } - }; - } - - protected static String cdAndRun(String targetDirectory, String command) { - return BashCommands.chain("mkdir -p '"+targetDirectory+"'", - "cd '"+targetDirectory+"'", - command); - } - - public static TaskFactory buildChefFile(String runDirectory, String chefDirectory, String phase, Iterable runList, - Map optionalAttributes) { - // TODO if it's server, try knife first - // TODO configure add'l properties - String phaseRb = - "root = " - + "'"+runDirectory+"'" - // recommended alternate to runDir is the following, but it is not available in some rubies - //+ File.absolute_path(File.dirname(__FILE__))"+ - + "\n"+ - "file_cache_path root\n"+ -// "cookbook_path root + '/cookbooks'\n"; - "cookbook_path '"+chefDirectory+"'\n"; - - Map phaseJsonMap = MutableMap.of(); - if (optionalAttributes!=null) - phaseJsonMap.putAll(optionalAttributes); - if (runList!=null) - phaseJsonMap.put("run_list", ImmutableList.copyOf(runList)); - Gson json = new GsonBuilder().create(); - String phaseJson = json.toJson(phaseJsonMap); - - return Tasks.sequential("build chef files for "+phase, - SshEffectorTasks.put(Urls.mergePaths(runDirectory)+"/"+phase+".rb").contents(phaseRb).createDirectory(), - SshEffectorTasks.put(Urls.mergePaths(runDirectory)+"/"+phase+".json").contents(phaseJson)); - } - - public static TaskFactory runChef(String runDir, String phase) { - // TODO chef server - return SshEffectorTasks.ssh(cdAndRun(runDir, "sudo chef-solo -c "+phase+".rb -j "+phase+".json -ldebug")). - summary("run chef for "+phase).requiringExitCodeZero(); - } - -} diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java deleted file mode 100644 index 68a1d50a53..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeConvergeTaskFactory.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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 extends KnifeTaskFactory { - - private static final Logger log = LoggerFactory.getLogger(KnifeConvergeTaskFactory.class); - - protected Function runList; - protected Map knifeAttributes = new MutableMap(); - protected List 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 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 initialKnifeParameters() { - // runs inside the task so can detect entity/machine at runtime - MutableList result = new MutableList(); - 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 knifeRunTwice(boolean runTwice) { - this.runTwice = runTwice; - return self(); - } - - /** whether to pass --sudo to knife; default true */ - public KnifeConvergeTaskFactory 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 knifeNodeName(String nodeName) { - this.nodeName = nodeName; - return self(); - } - - /** tell knife to use an explicit port */ - public KnifeConvergeTaskFactory 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 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 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 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 knifeRunList(Function runList) { - this.runList = runList; - return self(); - } - public KnifeConvergeTaskFactory 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 knifeAddAttributes(Map 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 KnifeConvergeTaskFactory returning(ScriptReturnType type) { - return (KnifeConvergeTaskFactory) super.returning(type); - } - - @Override - public KnifeConvergeTaskFactory returning(Function, RET2> resultTransformation) { - return (KnifeConvergeTaskFactory) super.returning(resultTransformation); - } - - @Override - public KnifeConvergeTaskFactory returningIsExitCodeZero() { - return (KnifeConvergeTaskFactory) super.returningIsExitCodeZero(); - } - - @Override - public KnifeConvergeTaskFactory requiringZeroAndReturningStdout() { - return (KnifeConvergeTaskFactory) super.requiringZeroAndReturningStdout(); - } - - @Override - public KnifeConvergeTaskFactory 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 diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java b/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java deleted file mode 100644 index 2623a19942..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/chef/KnifeTaskFactory.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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(). - *

- * 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: - *

  • {@link ChefConfig#KNIFE_EXECUTABLE} - *
  • {@link ChefConfig#KNIFE_CONFIG_FILE} - *

    - * (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 extends SystemProcessTaskFactory, RET>{ - - private static String KNIFE_PLACEHOLDER = ""; - public final String taskName; - protected String knifeExecutable; - protected List knifeParameters = new ArrayList(); - 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, Void>> getCompletionListeners() { - MutableList, Void>> result = MutableList.copyOf(super.getCompletionListeners()); - if (throwOnCommonKnifeErrors != Boolean.FALSE) - insertKnifeCompletionListenerIntoCompletionListenersList(result); - return result.asUnmodifiable(); - } - - public KnifeTaskFactory notThrowingOnCommonKnifeErrors() { - throwOnCommonKnifeErrors = false; - return self(); - } - - protected void insertKnifeCompletionListenerIntoCompletionListenersList(List, Void>> listeners) { - // give a nice warning if chef/knife not set up correctly - Function, Void> propagateIfKnifeConfigFileMissing = new Function, 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 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 addKnifeCommandToScript() { - add(KNIFE_PLACEHOLDER); - return self(); - } - - @Override - public List getCommands() { - MutableList result = new MutableList(); - 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 words = new MutableList(); - 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 initialKnifeParameters() { - return new MutableList(); - } - - @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 entityConfig(ConfigKey key) { - Entity entity = entity(); - if (entity!=null) - return entity.getConfig(key); - return null; - } - - public KnifeTaskFactory 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 knifeParameters() { - return knifeParameters; - } - - public KnifeTaskFactory knifeAddParameters(String word1, String ...words) { - knifeParameters.add(word1); - for (String w: words) - knifeParameters.add(w); - return self(); - } - - public KnifeTaskFactory 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 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 KnifeTaskFactory returning(ScriptReturnType type) { - return (KnifeTaskFactory) super.returning(type); - } - - @Override - public KnifeTaskFactory returning(Function, RET2> resultTransformation) { - return (KnifeTaskFactory) super.returning(resultTransformation); - } - - @Override - public KnifeTaskFactory returningIsExitCodeZero() { - return (KnifeTaskFactory) super.returningIsExitCodeZero(); - } - - @Override - public KnifeTaskFactory requiringZeroAndReturningStdout() { - return (KnifeTaskFactory) super.requiringZeroAndReturningStdout(); - } -} \ No newline at end of file diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java deleted file mode 100644 index 5c513e0092..0000000000 --- a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.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 encounteredTypes) { - return EntitySpec.create(ChefEntity.class) - .configure(ChefConfig.CHEF_COOKBOOK_PRIMARY_NAME, getLocalType(type)); - } - -} diff --git a/software/base/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver b/software/base/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver index 1224bd2672..9b45de17f4 100644 --- a/software/base/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver +++ b/software/base/src/main/resources/META-INF/services/org.apache.brooklyn.core.resolve.entity.EntitySpecResolver @@ -16,5 +16,4 @@ # specific language governing permissions and limitations # under the License. # -org.apache.brooklyn.entity.resolve.ChefEntitySpecResolver org.apache.brooklyn.entity.resolve.HardcodedCatalogEntitySpecResolver diff --git a/software/base/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/software/base/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 58c88a29c5..859a6a9056 100644 --- a/software/base/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/software/base/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -23,11 +23,6 @@ limitations under the License. http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd "> - - - 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")); - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java deleted file mode 100644 index ff389b054d..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefLiveTestSupport.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 targetLocation; - - @BeforeMethod(alwaysRun=true) - @Override - public void setUp() throws Exception { - super.setUp(); - - targetLocation = createLocation(); - } - - protected MachineProvisioningLocation 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 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 result = (MachineProvisioningLocation) - 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()); - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java deleted file mode 100644 index a7b5803928..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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). - *

    - * 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: - *

    - * https://manage.opscode.com/ - *

    - * with credentials for those with need to know (which is a lot of people, but not everyone - * with access to this github repo!). - *

    - * 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. - *

    - * Note that if you are porting an existing machine to be managed by a new chef account, you may need to do the following: - *

    - * ON management machine: - *

  • knife client delete HOST # or bulk delete, but don't delete your validator! it is a PITA recreating and adding back all the permissions! - *
  • knife node delete HOST - *

    - * ON machine being managed: - *

  • rm -rf /{etc,var}/chef - *

    - * 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 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 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()); - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java deleted file mode 100644 index 55fa4ff546..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/AbstractChefToyMySqlEntityLiveTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 createLocation() { - return ChefLiveTestSupport.createLocation(mgmt); - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java deleted file mode 100644 index a0bfba2304..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 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)); - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java deleted file mode 100644 index 70b20ad240..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/ChefSoloDriverToyMySqlEntity.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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>> IS_RUNNING_TASK = - ConfigKeys.newConfigKeyWithDefault(ChefSoloDriver.IS_RUNNING_TASK, - SshEffectorTasks.isPidFromFileRunning(PID_FILE).runAsRoot()); - - public static final ConfigKey> 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(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'] - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java deleted file mode 100644 index 0102f6e9b6..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefAutodetectToyMySqlEntityLiveTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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; - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java deleted file mode 100644 index 566a96e5cf..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefServerToyMySqlEntityLiveTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - *

    - * 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; - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java deleted file mode 100644 index ba6c6d91f7..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicChefSoloToyMySqlEntityLiveTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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; - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java deleted file mode 100644 index 2edd8a1a0e..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/DynamicToyMySqlEntityChef.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 specBase() { - EntitySpec 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 spec() { - EntitySpec spec = specBase(); - log.debug("Created entity spec for MySql: "+spec); - return spec; - } - - public static EntitySpec specSolo() { - EntitySpec spec = specBase(); - spec.configure(ChefConfig.CHEF_MODE, ChefConfig.ChefModes.SOLO); - log.debug("Created entity spec for MySql: "+spec); - return spec; - } - - public static EntitySpec specKnife() { - EntitySpec spec = specBase(); - spec.configure(ChefConfig.CHEF_MODE, ChefConfig.ChefModes.KNIFE); - log.debug("Created entity spec for MySql: "+spec); - return spec; - } - -} diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java b/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java deleted file mode 100644 index c02dbc6091..0000000000 --- a/software/base/src/test/java/org/apache/brooklyn/entity/chef/mysql/TypedToyMySqlEntityChef.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.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); - } - -}