You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by m4...@apache.org on 2017/09/29 09:47:31 UTC
[2/3] brooklyn-server git commit: Move chef to own module in
brooklyn-library
Move chef to own module in brooklyn-library
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d113c7f8
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d113c7f8
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d113c7f8
Branch: refs/heads/master
Commit: d113c7f856c1c3a9855d1fb71c5188234fba3561
Parents: 1dcd797
Author: Aled Sage <al...@gmail.com>
Authored: Fri Sep 15 21:00:28 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 27 21:05:22 2017 +0100
----------------------------------------------------------------------
.../brooklyn/entity/chef/ChefAttributeFeed.java | 413 -------------------
.../entity/chef/ChefAttributePollConfig.java | 61 ---
.../brooklyn/entity/chef/ChefBashCommands.java | 42 --
.../apache/brooklyn/entity/chef/ChefConfig.java | 94 -----
.../brooklyn/entity/chef/ChefConfigs.java | 102 -----
.../apache/brooklyn/entity/chef/ChefEntity.java | 26 --
.../brooklyn/entity/chef/ChefEntityImpl.java | 39 --
.../entity/chef/ChefLifecycleEffectorTasks.java | 364 ----------------
.../brooklyn/entity/chef/ChefServerTasks.java | 97 -----
.../brooklyn/entity/chef/ChefSoloDriver.java | 85 ----
.../brooklyn/entity/chef/ChefSoloTasks.java | 70 ----
.../apache/brooklyn/entity/chef/ChefTasks.java | 154 -------
.../entity/chef/KnifeConvergeTaskFactory.java | 249 -----------
.../brooklyn/entity/chef/KnifeTaskFactory.java | 241 -----------
.../entity/resolve/ChefEntitySpecResolver.java | 42 --
...oklyn.core.resolve.entity.EntitySpecResolver | 1 -
.../resources/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 ----
...micChefAutodetectToyMySqlEntityLiveTest.java | 43 --
...DynamicChefServerToyMySqlEntityLiveTest.java | 50 ---
.../DynamicChefSoloToyMySqlEntityLiveTest.java | 43 --
.../chef/mysql/DynamicToyMySqlEntityChef.java | 81 ----
.../chef/mysql/TypedToyMySqlEntityChef.java | 55 ---
29 files changed, 2788 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributeFeed.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 f6d2615..0000000
--- 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.
- *
- * <p>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 <tt>chef.attribute.</tt>
- * followed by a period-separated path through the Chef attribute hierarchy. For example, an attribute sensor named
- * <tt>chef.attribute.sql_server.instance_name</tt> would cause the feed to search for a Chef attribute called
- * <tt>sql_server</tt>, and within that an attribute <tt>instance_name</tt>, and set the sensor to the value of this
- * attribute.</p>
- *
- * <p>This feed uses the <tt>knife</tt> 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.</p>
- *
- * <p>Example:</p>
- *
- * {@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<Set<ChefAttributePollConfig<?>>> POLLS = ConfigKeys.newConfigKey(
- new TypeToken<Set<ChefAttributePollConfig<?>>>() {},
- "polls");
-
- public static final ConfigKey<String> 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<ChefAttributePollConfig> 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<String, AttributeSensor> sensors) {
- for (Map.Entry<String, AttributeSensor> 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<AttributeSensor> 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<String> 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<ChefAttributePollConfig<?>> 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<ChefAttributePollConfig<?>> polls = getConfig(POLLS);
-
- long minPeriod = Integer.MAX_VALUE;
- for (ChefAttributePollConfig<?> config : polls) {
- minPeriod = Math.min(minPeriod, config.getPeriod());
- }
-
- knifeTaskFactory = new KnifeNodeAttributeQueryTaskFactory(nodeName);
-
- final Callable<SshPollValue> getAttributesFromKnife = new Callable<SshPollValue>() {
- @Override
- public SshPollValue call() throws Exception {
- ProcessTaskWrapper<String> 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<SshPollValue>(entity, getAttributesFromKnife),
- new SendChefAttributesToSensors(entity, polls),
- minPeriod);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- protected Poller<SshPollValue> getPoller() {
- return (Poller<SshPollValue>) super.getPoller();
- }
-
- /**
- * An implementation of {@link KnifeTaskFactory} that queries for the attributes of a node.
- */
- private static class KnifeNodeAttributeQueryTaskFactory extends KnifeTaskFactory<String> {
- private final String nodeName;
-
- public KnifeNodeAttributeQueryTaskFactory(String nodeName) {
- super("retrieve attributes of node " + nodeName);
- this.nodeName = nodeName;
- }
-
- @Override
- protected List<String> 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 <T> The type of the {@link Callable}.
- */
- private static class CallInEntityExecutionContext<T> implements Callable<T> {
-
- private final Callable<T> job;
- private Entity entity;
-
- private CallInEntityExecutionContext(Entity entity, Callable<T> 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 <tt>knife</tt> invocation and sets the appropriate sensors.
- */
- private static class SendChefAttributesToSensors implements PollHandler<SshPollValue> {
- private static final Iterable<String> 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<String, AttributeSensor<?>> chefAttributeSensors;
-
- public SendChefAttributesToSensors(Entity entity, Set<ChefAttributePollConfig<?>> 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<String, AttributeSensor<?>> attribute : chefAttributeSensors.entrySet()) {
- String chefAttributeName = attribute.getKey();
- AttributeSensor<?> sensor = attribute.getValue();
- log.trace("Finding value for attribute sensor " + sensor.getName());
-
- Iterable<String> path = SPLITTER.split(chefAttributeName);
- JsonElement elementForSensor = null;
- for(String prefix : PREFIXES) {
- Iterable<String> 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<String> 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<String> 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;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefAttributePollConfig.java
----------------------------------------------------------------------
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 c090f34..0000000
--- 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<T> extends PollConfig<Object, T, ChefAttributePollConfig<T>>{
-
- private String chefAttributePath;
-
- public static <T> ChefAttributePollConfig<T> forSensor(AttributeSensor<T> sensor) {
- return new ChefAttributePollConfig<T>(sensor);
- }
-
- public static ChefAttributePollConfig<Void> forMultiple() {
- return new ChefAttributePollConfig<Void>(PollConfig.NO_SENSOR);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public ChefAttributePollConfig(AttributeSensor<T> sensor) {
- super(sensor);
- onSuccess((Function)Functions.identity());
- }
-
- public ChefAttributePollConfig(ChefAttributePollConfig<T> other) {
- super(other);
- this.chefAttributePath = other.chefAttributePath;
- }
-
- public String getChefAttributePath() {
- return chefAttributePath;
- }
-
- public ChefAttributePollConfig<T> chefAttributePath(String val) {
- this.chefAttributePath = val; return this;
- }
-
- @Override protected String toStringBaseName() { return "chef"; }
- @Override protected String toStringPollSource() { return chefAttributePath; }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefBashCommands.java
----------------------------------------------------------------------
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 dde58d3..0000000
--- 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")+" )");
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfig.java
----------------------------------------------------------------------
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 07b4ce5..0000000
--- 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<String> 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<String> CHEF_COOKBOOK_URLS = new MapConfigKey<String>(String.class, "brooklyn.chef.cookbooksUrls");
-
- @SetFromFlag("converge_twice")
- public static final ConfigKey<Boolean> 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<String> CHEF_RUN_LIST = new SetConfigKey<String>(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<String> CHEF_LAUNCH_RUN_LIST = new SetConfigKey<String>(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<Object> CHEF_LAUNCH_ATTRIBUTES = new MapConfigKey<Object>(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<ChefModes> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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");
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefConfigs.java
----------------------------------------------------------------------
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 16d5fa0..0000000
--- 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<? extends Object,? extends Object> attributesMap) {
- entity.configure(ChefConfig.CHEF_LAUNCH_ATTRIBUTES, MapModifications.add((Map)attributesMap));
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void addLaunchAttributes(EntityInternal entity, Map<? extends Object,? extends Object> 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> T getRequiredConfig(Entity entity, ConfigKey<T> key) {
- return Preconditions.checkNotNull(
- Preconditions.checkNotNull(entity, "Entity must be supplied").getConfig(key),
- "Key "+key+" is required on "+entity);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntity.java
----------------------------------------------------------------------
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 1b1f866..0000000
--- 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 {
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefEntityImpl.java
----------------------------------------------------------------------
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 6bc3cfd..0000000
--- 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
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
----------------------------------------------------------------------
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 8c3dad9..0000000
--- 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.
- * <p>
- * 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<Boolean> 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<MachineLocation> 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<String, String> 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<MutableMap<Object, Object>> 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<? extends String> 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<String, Object>) 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<MutableMap<Object, Object>> 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<? extends String> 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<Integer> 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<String> config key ?
- TaskTags.markInessential(
- new KnifeTaskFactory<String>("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;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefServerTasks.java
----------------------------------------------------------------------
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 c81ff9d..0000000
--- 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<Boolean> isKnifeInstalled() {
- return new KnifeTaskFactory<Boolean>("knife install check")
- .knifeAddParameters("node list")
- .notThrowingOnCommonKnifeErrors()
- .returningIsExitCodeZero();
- }
-
- /** plain knife converge task - run list must be set, other arguments are optional */
- public static KnifeConvergeTaskFactory<String> knifeConvergeTask() {
- return new KnifeConvergeTaskFactory<String>("knife converge")
- .requiringZeroAndReturningStdout();
- }
- /** knife converge task configured for this run list (and sudo) */
- public static KnifeConvergeTaskFactory<String> knifeConvergeRunList(String runList) {
- return knifeConvergeTask()
- .knifeRunList(runList)
- .knifeSudo(true);
- }
-
- /** knife converge task configured for this run list on windows (ssh) */
- public static KnifeConvergeTaskFactory<String> 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<String> knifeConvergeRunListWindowsWinrm(String runList) {
- return knifeConvergeTask()
- .knifeRunList(runList)
- .knifeSudo(false)
- .knifeAddExtraBootstrapParameters("windows winrm")
- .knifePortUseKnifeDefault();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloDriver.java
----------------------------------------------------------------------
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 6ee1786..0000000
--- 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<TaskFactory<? extends TaskAdaptable<Boolean>>> IS_RUNNING_TASK = ConfigKeys.newConfigKey(
- new TypeToken<TaskFactory<? extends TaskAdaptable<Boolean>>>() {},
- "brooklyn.chef.task.driver.isRunningTask");
-
- @SuppressWarnings("serial")
- public static final ConfigKey<TaskFactory<?>> STOP_TASK = ConfigKeys.newConfigKey(
- new TypeToken<TaskFactory<?>>() {},
- "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> T getRequiredConfig(ConfigKey<T> key) {
- return ChefConfigs.getRequiredConfig(getEntity(), key);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefSoloTasks.java
----------------------------------------------------------------------
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 505f37e..0000000
--- 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<String,String> 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<? extends String> runList,
- Map<String, Object> 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();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d113c7f8/software/base/src/main/java/org/apache/brooklyn/entity/chef/ChefTasks.java
----------------------------------------------------------------------
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 e2edcb2..0000000
--- 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<String,String> cookbooksAndUrls, final boolean force) {
- return Tasks.<Void>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<TaskAdaptable<?>>() {
- @Override
- public TaskAdaptable<?> newTask() {
- TaskBuilder<Void> tb = Tasks.<Void>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<? extends String> runList,
- Map<String, Object> 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<String,Object> 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();
- }
-
-}