brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [1/7] brooklyn-library git commit: Moving Ansible as a module so it matches the new CM structure
Date Fri, 19 Feb 2016 10:07:38 GMT
Repository: brooklyn-library
Updated Branches:
  refs/heads/master 9fdf1dbf6 -> b8395ff30


Moving Ansible as a module so it matches the new CM structure

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

Branch: refs/heads/master
Commit: c1a87838197f172ec5179831ba3824f0ead117a4
Parents: 121db32
Author: Yavor Yanchev <yavor@yanchev.com>
Authored: Tue Feb 16 11:10:07 2016 +0200
Committer: Yavor Yanchev <yavor@yanchev.com>
Committed: Wed Feb 17 11:43:03 2016 +0200

----------------------------------------------------------------------
 software/cm/ansible/pom.xml                     |  84 ++++++++
 .../entity/cm/ansible/AnsibleBashCommands.java  |  38 ++++
 .../entity/cm/ansible/AnsibleConfig.java        |  66 ++++++
 .../entity/cm/ansible/AnsibleEntity.java        |  40 ++++
 .../entity/cm/ansible/AnsibleEntityImpl.java    |  61 ++++++
 .../ansible/AnsibleLifecycleEffectorTasks.java  | 203 +++++++++++++++++++
 .../entity/cm/ansible/AnsiblePlaybookTasks.java | 109 ++++++++++
 .../ansible/AnsibleEntityIntegrationTest.java   | 116 +++++++++++
 software/cm/pom.xml                             |  53 +----
 .../entity/cm/ansible/AnsibleBashCommands.java  |  38 ----
 .../entity/cm/ansible/AnsibleConfig.java        |  66 ------
 .../entity/cm/ansible/AnsibleEntity.java        |  40 ----
 .../entity/cm/ansible/AnsibleEntityImpl.java    |  61 ------
 .../ansible/AnsibleLifecycleEffectorTasks.java  | 203 -------------------
 .../entity/cm/ansible/AnsiblePlaybookTasks.java | 109 ----------
 .../ansible/AnsibleEntityIntegrationTest.java   | 116 -----------
 16 files changed, 718 insertions(+), 685 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/pom.xml
----------------------------------------------------------------------
diff --git a/software/cm/ansible/pom.xml b/software/cm/ansible/pom.xml
new file mode 100644
index 0000000..028d73d
--- /dev/null
+++ b/software/cm/ansible/pom.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>brooklyn-software-cm-ansible</artifactId>
+  <packaging>jar</packaging>
+  <name>Brooklyn CM Ansible</name>
+  <description>Brooklyn entities for Configuration Management using Ansible</description>
+
+
+    <parent>
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-library</artifactId>
+        <version>0.9.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-software-base</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+         <groupId>org.apache.brooklyn</groupId>
+         <artifactId>brooklyn-camp</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-test-support</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-core</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-software-base</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+
+      <dependency>
+          <groupId>org.assertj</groupId>
+          <artifactId>assertj-core</artifactId>
+          <version>${assertj.version}</version>
+          <scope>test</scope>
+      </dependency>
+
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
new file mode 100644
index 0000000..e22ee34
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
@@ -0,0 +1,38 @@
+/*
+ * 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.cm.ansible;
+
+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.installExecutable;
+import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
+
+import org.apache.brooklyn.util.ssh.BashCommands;
+
+public class AnsibleBashCommands {
+
+    public static final String INSTALL_ANSIBLE =
+            BashCommands.chain(
+                    sudo("apt-add-repository -y ppa:ansible/ansible"),
+                    INSTALL_CURL,
+                    INSTALL_TAR,
+                    INSTALL_UNZIP,
+                    installExecutable("ansible"));
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
new file mode 100644
index 0000000..d63c2c6
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
@@ -0,0 +1,66 @@
+/*
+ * 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.cm.ansible;
+
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.util.core.flags.SetFromFlag;
+
+import com.google.common.annotations.Beta;
+
+/** {@link ConfigKey}s used to configure Ansible */
+@Beta
+public interface AnsibleConfig {
+
+    enum AnsibleModes {
+        PLAYBOOK
+    };
+
+    @SetFromFlag("playbook")
+    ConfigKey<String> ANSIBLE_PLAYBOOK = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbook",
+        "Playbook to be execute by Ansible");
+
+    @SetFromFlag("playbook.yaml")
+    ConfigKey<String> ANSIBLE_PLAYBOOK_YAML = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookYaml",
+        "Playbook to be execute by Ansible");
+
+    @SetFromFlag("playbook.url")
+    ConfigKey<String> ANSIBLE_PLAYBOOK_URL = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookUrl");
+
+    @SetFromFlag("ansible.service.start")
+    ConfigKey<String> ANSIBLE_SERVICE_START = ConfigKeys.newStringConfigKey("ansible.service.start",
+            "Default start command used with conjunction with the Ansible's service module",
+            "sudo ansible localhost -c local -m service -a \"name=%s state=started\"");
+
+    @SetFromFlag("ansible.service.stop")
+    ConfigKey<String> ANSIBLE_SERVICE_STOP = ConfigKeys.newStringConfigKey("ansible.service.stop",
+            "Default stop command used with conjunction with the Ansible's service module",
+            "sudo ansible localhost -c local -m service -a \"name=%s state=stopped\"");
+
+    @SetFromFlag("ansible.service.checkPort")
+    ConfigKey<Integer> ANSIBLE_SERVICE_CHECK_PORT = ConfigKeys.newIntegerConfigKey("ansible.service.check.port");
+
+    @SetFromFlag("service.name")
+    ConfigKey<String> SERVICE_NAME = ConfigKeys.newStringConfigKey("brooklyn.ansible.serviceName",
+        "Name of OS service this will run as, for use in checking running and stopping");
+
+    @SetFromFlag("ansible.vars")
+    ConfigKey<Object> ANSIBLE_VARS = ConfigKeys.newConfigKey(Object.class, "brooklyn.ansible.vars",
+        "Ansible 'extra-vars' variable configuration values");
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
new file mode 100644
index 0000000..a2c9676
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.cm.ansible;
+
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.core.annotation.Effector;
+import org.apache.brooklyn.core.annotation.EffectorParam;
+import org.apache.brooklyn.core.effector.MethodEffector;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+
+@ImplementedBy(AnsibleEntityImpl.class)
+public interface AnsibleEntity extends SoftwareProcess, AnsibleConfig {
+
+    MethodEffector<String> ANSIBLE_COMMAND = new MethodEffector<>(AnsibleEntity.class, "ansibleCommand");
+
+    @Effector(description = "Invoke an arbitrary Ansible command, optionally specifying the module (default is 'command')")
+    String ansibleCommand(
+        @EffectorParam(name="module", description = "Name of the Ansible module to invoke", defaultValue = "command")
+        String module,
+        @EffectorParam(name="args", description = "Arguments for the ansible command")
+        String args
+    );
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java
new file mode 100644
index 0000000..c2635ca
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.cm.ansible;
+
+import org.apache.brooklyn.entity.stock.EffectorStartableImpl;
+import org.apache.brooklyn.util.core.task.DynamicTasks;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.text.Strings;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class AnsibleEntityImpl extends EffectorStartableImpl implements AnsibleEntity {
+
+    private AnsibleLifecycleEffectorTasks lifecycleTasks;
+
+    public void init() {
+        checkNotNull(getConfig(SERVICE_NAME), "service name is missing. it has to be provided by the user");
+        String playbookName = getConfig(ANSIBLE_PLAYBOOK);
+        if (!Strings.isBlank(playbookName)) setDefaultDisplayName(playbookName + " (ansible)");
+
+        super.init();
+
+        lifecycleTasks = new AnsibleLifecycleEffectorTasks();
+
+        lifecycleTasks.attachLifecycleEffectors(this);
+    }
+
+    @Override
+    public void populateServiceNotUpDiagnostics() {
+        // TODO no-op currently; should check ssh'able etc
+    }
+
+    @Override
+    public String ansibleCommand(String module, String args) {
+        final ProcessTaskWrapper<Integer> command = DynamicTasks.queue(
+            AnsiblePlaybookTasks.moduleCommand(module, config().get(ANSIBLE_VARS), lifecycleTasks.getRunDir(), args));
+        command.asTask().blockUntilEnded();
+        if (0 == command.getExitCode()) {
+            return command.getStdout();
+        } else {
+            throw new RuntimeException("Command (" + args + ") in module " + module
+                + " failed with stderr:\n" + command.getStderr() + "\n");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
new file mode 100644
index 0000000..e1a8622
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
@@ -0,0 +1,203 @@
+/*
+ * 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.cm.ansible;
+
+import com.google.common.base.Supplier;
+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.entity.trait.Startable;
+import org.apache.brooklyn.core.location.Locations;
+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.feed.ssh.SshFeed;
+import org.apache.brooklyn.feed.ssh.SshPollConfig;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.core.task.DynamicTasks;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.net.Urls;
+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;
+
+public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements AnsibleConfig {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AnsibleLifecycleEffectorTasks.class);
+
+    protected String serviceName;
+    protected SshFeed serviceSshFeed;
+
+    protected Object extraVars;
+    protected String baseDir;
+    protected String runDir;
+
+    public AnsibleLifecycleEffectorTasks() {
+    }
+
+    public String getServiceName() {
+        if (serviceName!=null) return serviceName;
+        return serviceName = entity().config().get(AnsibleConfig.SERVICE_NAME);
+    }
+
+    public Object getExtraVars() {
+        if (extraVars != null) return extraVars;
+        return extraVars = entity().config().get(ANSIBLE_VARS);
+    }
+
+    public String getBaseDir() {
+        if (null != baseDir) return baseDir;
+        return baseDir = MachineLifecycleEffectorTasks.resolveOnBoxDir(entity(),
+                Machines.findUniqueMachineLocation(entity().getLocations(), SshMachineLocation.class).get());
+    }
+
+    public String getRunDir() {
+        if (null != runDir) return runDir;
+        return runDir = Urls.mergePaths(getBaseDir(), "apps/"+entity().getApplicationId()+"/ansible/playbooks/"
+            +entity().getEntityType().getSimpleName()+"_"+entity().getId());
+    }
+
+    @Override
+    public void attachLifecycleEffectors(Entity entity) {
+        if (getServiceName()==null && getClass().equals(AnsibleLifecycleEffectorTasks.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);
+    }
+
+    @Override
+    protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
+        startWithAnsibleAsync();
+
+        return "ansible start tasks submitted";
+    }
+
+    protected String getPlaybookName() {
+        return entity().config().get(ANSIBLE_PLAYBOOK);
+    }
+
+    protected void startWithAnsibleAsync() {
+        String installDir = Urls.mergePaths(getBaseDir(), "installs/ansible");
+
+        String playbookUrl = entity().config().get(ANSIBLE_PLAYBOOK_URL);
+        String playbookYaml = entity().config().get(ANSIBLE_PLAYBOOK_YAML);
+
+        if (Strings.isNonBlank(playbookUrl) && Strings.isNonBlank(playbookYaml)) {
+            throw new IllegalArgumentException("You can specify " +  AnsibleConfig.ANSIBLE_PLAYBOOK_URL.getName()
+                +  " or " + AnsibleConfig.ANSIBLE_PLAYBOOK_YAML.getName() + " but not both of them!");
+        }
+
+        DynamicTasks.queue(AnsiblePlaybookTasks.installAnsible(installDir, false));
+
+        if (getExtraVars() != null) {
+            DynamicTasks.queue(AnsiblePlaybookTasks.configureExtraVars(getRunDir(), extraVars, false));
+        }
+
+        if (Strings.isNonBlank(playbookUrl)) {
+            DynamicTasks.queue(AnsiblePlaybookTasks.installPlaybook(getRunDir(), getPlaybookName(), playbookUrl));
+        }
+
+        if (Strings.isNonBlank(playbookYaml)) {
+            DynamicTasks.queue(AnsiblePlaybookTasks.buildPlaybookFile(getRunDir(), getPlaybookName()));
+        }
+        DynamicTasks.queue(AnsiblePlaybookTasks.runAnsible(getRunDir(), getExtraVars(), getPlaybookName()));
+    }
+
+
+    protected void postStartCustom() {
+        boolean result = false;
+        result |= tryCheckStartService();
+
+        if (!result) {
+            LOG.warn("No way to check whether "+entity()+" is running; assuming yes");
+        }
+        entity().sensors().set(SoftwareProcess.SERVICE_UP, true);
+        
+        Maybe<SshMachineLocation> machine = Locations.findUniqueSshMachineLocation(entity().getLocations());
+
+        if (machine.isPresent()) {
+            
+            String serviceName = String.format("[%s]%s", entity().config().get(SERVICE_NAME).substring(0, 1),
+                    entity().config().get(SERVICE_NAME).substring(1));
+            String checkCmd = String.format("ps -ef | grep %s", serviceName);
+
+            Integer serviceCheckPort = entity().config().get(ANSIBLE_SERVICE_CHECK_PORT);
+
+            if (serviceCheckPort != null) {
+                checkCmd = String.format("sudo ansible localhost -c local -m wait_for -a \"host=0.0.0.0 port=%d\"", serviceCheckPort);
+            }
+            serviceSshFeed = SshFeed.builder()
+                    .entity(entity())
+                    .period(Duration.ONE_MINUTE)
+                    .machine(machine.get())
+                    .poll(new SshPollConfig<Boolean>(Startable.SERVICE_UP)
+                            .command(checkCmd)
+                            .setOnSuccess(true)
+                            .setOnFailureOrException(false))
+                    .build();
+                    
+             entity().feeds().addFeed(serviceSshFeed);
+        } else {
+            LOG.warn("Location(s) {} not an ssh-machine location, so not polling for status; setting serviceUp immediately", entity().getLocations());
+        }
+    }
+
+    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(String.format(entity().config().get(AnsibleConfig.ANSIBLE_SERVICE_START), getServiceName()))).get())) {
+            throw new IllegalStateException("The process for "+entity()+" appears not to be running (service "+getServiceName()+")");
+        }
+
+        return true;
+    }
+
+    @Override
+    protected String stopProcessesAtMachine() {
+        boolean result = false;
+        result |= tryStopService();
+        if (!result) {
+            throw new IllegalStateException("The process for "+entity()+" could not be stopped (no impl!)");
+        }
+        return "stopped";
+    }
+
+    @Override
+    protected StopMachineDetails<Integer> stopAnyProvisionedMachines() {
+        return super.stopAnyProvisionedMachines();
+    }
+
+    protected boolean tryStopService() {
+        if (getServiceName()==null) return false;
+        int result = DynamicTasks.queue(SshEffectorTasks.ssh(String.format(entity().config().get(AnsibleConfig.ANSIBLE_SERVICE_STOP), getServiceName()))).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)");
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java
new file mode 100644
index 0000000..36076a1
--- /dev/null
+++ b/software/cm/ansible/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.entity.cm.ansible;
+
+import org.apache.brooklyn.api.entity.Entity;
+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.core.ResourceUtils;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.util.net.Urls;
+import org.apache.brooklyn.util.ssh.BashCommands;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
+
+public class AnsiblePlaybookTasks {
+    private static final Logger LOG = LoggerFactory.getLogger(AnsiblePlaybookTasks.class);
+    private static final String EXTRA_VARS_FILENAME = "extra_vars.yaml";
+
+    public static TaskFactory<?> installAnsible(String ansibleDirectory, boolean force) {
+        String installCmd = cdAndRun(ansibleDirectory, AnsibleBashCommands.INSTALL_ANSIBLE);
+        if (!force) installCmd = BashCommands.alternatives("which ansible", installCmd);
+        return SshEffectorTasks.ssh(installCmd).summary("install ansible");
+    }
+
+    public static TaskFactory<?> installPlaybook(final String ansibleDirectory, final String playbookName, final String playbookUrl) {
+        return Tasks.sequential("build ansible playbook file for "+playbookName,
+                SshEffectorTasks.put(ansibleDirectory + "/" + playbookName + ".yaml")
+                    .contents(ResourceUtils.create().getResourceFromUrl(playbookUrl))
+                    .createDirectory());
+    }
+    
+    protected static String cdAndRun(String targetDirectory, String command) {
+        return BashCommands.chain("mkdir -p "+targetDirectory,
+                "cd "+targetDirectory,
+                command);
+    }
+
+    public static TaskFactory<?> buildPlaybookFile(final String ansibleDirectory, String playbook) {
+        Entity entity = EffectorTasks.findEntity();
+        String yaml = entity.config().get(AnsibleConfig.ANSIBLE_PLAYBOOK_YAML);
+
+        return Tasks.sequential("build ansible playbook file for "+ playbook,
+            SshEffectorTasks.put(Urls.mergePaths(ansibleDirectory) + "/" + playbook + ".yaml")
+                .contents(yaml).createDirectory());
+    }
+
+    public static TaskFactory<?> runAnsible(final String dir, Object extraVars, String playbookName) {
+        String cmd = String.format("sudo ansible-playbook -i \"localhost,\" -c local "
+            + optionalExtraVarsParameter(extraVars)
+            + " -s %s.yaml", playbookName);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Ansible command: {}", cmd);
+        }
+
+        return SshEffectorTasks.ssh(cdAndRun(dir, cmd)).
+                summary("run ansible playbook for " + playbookName).requiringExitCodeZero();
+    }
+
+    public static ProcessTaskFactory<Integer> moduleCommand(String module, Object extraVars, String root, String args) {
+        final String command = "ansible localhost "
+            + optionalExtraVarsParameter(extraVars)
+            + " -m '" + module + "' -a '" + args + "'";
+        return SshEffectorTasks.ssh(sudo(BashCommands.chain("cd " + root, command)))
+            .summary("ad-hoc: " + command).requiringExitCodeZero();
+    }
+
+    public static TaskFactory<?> configureExtraVars(String dir, Object extraVars, boolean force) {
+        DumperOptions options = new DumperOptions();
+        options.setDefaultScalarStyle(DumperOptions.ScalarStyle.DOUBLE_QUOTED);
+        Yaml asYaml = new Yaml(options);
+        final String varsYaml = asYaml.dump(extraVars);
+        return SshEffectorTasks.put(Urls.mergePaths(dir, EXTRA_VARS_FILENAME))
+            .contents(varsYaml)
+            .summary("install extra vars")
+            .createDirectory();
+    }
+
+    private static String optionalExtraVarsParameter(Object extraVars) {
+        if (null == extraVars || Strings.isBlank(extraVars.toString())) {
+            return "";
+        }
+        return " --extra-vars \"@" + EXTRA_VARS_FILENAME + "\" ";
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/ansible/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/cm/ansible/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java b/software/cm/ansible/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
new file mode 100644
index 0000000..76e993d
--- /dev/null
+++ b/software/cm/ansible/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.cm.ansible;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.MachineDetails;
+import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.location.BasicMachineDetails;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+
+public class AnsibleEntityIntegrationTest {
+    protected TestApplication app;
+    protected LocalhostMachineProvisioningLocation testLocation;
+    protected AnsibleEntity ansible;
+    protected SshMachineLocation sshHost;
+
+    String playbookYaml = Joiner.on("\n").join(
+            "---",
+            "- hosts: localhost",
+            "  sudo: True",
+            "",
+            "  tasks:",
+            "  - apt: name=apache2 state=latest",
+            "    when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'",
+            "",
+            "  - yum: name=httpd state=latest",
+            "    when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'",
+            "",
+            "  - service: name=apache2 state=started enabled=no",
+            "    when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'",
+            "",
+            "  - service: name=httpd state=started enabled=no",
+            "    when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'");
+
+    @BeforeMethod(alwaysRun = true)
+    public void setup() throws Exception {
+        app = TestApplication.Factory.newManagedInstanceForTests();;
+        testLocation = new LocalhostMachineProvisioningLocation();
+        sshHost = testLocation.obtain();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void shutdown() {
+        Entities.destroyAll(app.getManagementContext());
+    }
+    
+    @Test(groups = {"Integration"})
+    public void testAnsible() {
+        Task<BasicMachineDetails> detailsTask = app.getExecutionContext().submit(
+                BasicMachineDetails.taskForSshMachineLocation(sshHost));
+        MachineDetails machine = detailsTask.getUnchecked();
+
+
+        OsDetails details = machine.getOsDetails();
+        
+        String osName = details.getName();
+        String playbookServiceName = getPlaybookServiceName(osName);
+        ansible = app.createAndManageChild(EntitySpec.create(AnsibleEntity.class)
+                .configure("playbook.yaml", playbookYaml)
+                .configure("playbook", playbookServiceName)
+                .configure("service.name", playbookServiceName));
+
+        app.start(ImmutableList.of(testLocation));
+        EntityAsserts.assertAttributeEqualsEventually(ansible, Startable.SERVICE_UP, true);
+
+        ansible.stop();
+        EntityAsserts.assertAttributeEqualsEventually(ansible, Startable.SERVICE_UP, false);
+    }
+
+    private String getPlaybookServiceName(String os) {
+        String name;
+
+        switch (os.toLowerCase()) {
+            case "fedora":
+                name = "httpd";
+                break;
+            case "centos":
+                name = "httpd";
+                break;
+            default:
+                name = "apache2";
+        }
+        return name;
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/pom.xml
----------------------------------------------------------------------
diff --git a/software/cm/pom.xml b/software/cm/pom.xml
index ea17774..8a86fb7 100644
--- a/software/cm/pom.xml
+++ b/software/cm/pom.xml
@@ -70,61 +70,10 @@
         </mailingList>
     </mailingLists>
 
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-api</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-software-base</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-software-database</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-         <groupId>org.apache.brooklyn</groupId>
-         <artifactId>brooklyn-camp</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-test-support</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-core</artifactId>
-      <version>${project.version}</version>
-      <classifier>tests</classifier>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.brooklyn</groupId>
-      <artifactId>brooklyn-software-base</artifactId>
-      <version>${project.version}</version>
-      <classifier>tests</classifier>
-      <scope>test</scope>
-    </dependency>
-
-      <dependency>
-          <groupId>org.assertj</groupId>
-          <artifactId>assertj-core</artifactId>
-          <version>${assertj.version}</version>
-          <scope>test</scope>
-      </dependency>
-  </dependencies>
-
     <modules>
 
         <module>salt</module>
+        <module>ansible</module>
 
     </modules>
 

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
deleted file mode 100644
index e22ee34..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleBashCommands.java
+++ /dev/null
@@ -1,38 +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.cm.ansible;
-
-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.installExecutable;
-import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
-
-import org.apache.brooklyn.util.ssh.BashCommands;
-
-public class AnsibleBashCommands {
-
-    public static final String INSTALL_ANSIBLE =
-            BashCommands.chain(
-                    sudo("apt-add-repository -y ppa:ansible/ansible"),
-                    INSTALL_CURL,
-                    INSTALL_TAR,
-                    INSTALL_UNZIP,
-                    installExecutable("ansible"));
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
deleted file mode 100644
index d63c2c6..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleConfig.java
+++ /dev/null
@@ -1,66 +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.cm.ansible;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-
-import com.google.common.annotations.Beta;
-
-/** {@link ConfigKey}s used to configure Ansible */
-@Beta
-public interface AnsibleConfig {
-
-    enum AnsibleModes {
-        PLAYBOOK
-    };
-
-    @SetFromFlag("playbook")
-    ConfigKey<String> ANSIBLE_PLAYBOOK = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbook",
-        "Playbook to be execute by Ansible");
-
-    @SetFromFlag("playbook.yaml")
-    ConfigKey<String> ANSIBLE_PLAYBOOK_YAML = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookYaml",
-        "Playbook to be execute by Ansible");
-
-    @SetFromFlag("playbook.url")
-    ConfigKey<String> ANSIBLE_PLAYBOOK_URL = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookUrl");
-
-    @SetFromFlag("ansible.service.start")
-    ConfigKey<String> ANSIBLE_SERVICE_START = ConfigKeys.newStringConfigKey("ansible.service.start",
-            "Default start command used with conjunction with the Ansible's service module",
-            "sudo ansible localhost -c local -m service -a \"name=%s state=started\"");
-
-    @SetFromFlag("ansible.service.stop")
-    ConfigKey<String> ANSIBLE_SERVICE_STOP = ConfigKeys.newStringConfigKey("ansible.service.stop",
-            "Default stop command used with conjunction with the Ansible's service module",
-            "sudo ansible localhost -c local -m service -a \"name=%s state=stopped\"");
-
-    @SetFromFlag("ansible.service.checkPort")
-    ConfigKey<Integer> ANSIBLE_SERVICE_CHECK_PORT = ConfigKeys.newIntegerConfigKey("ansible.service.check.port");
-
-    @SetFromFlag("service.name")
-    ConfigKey<String> SERVICE_NAME = ConfigKeys.newStringConfigKey("brooklyn.ansible.serviceName",
-        "Name of OS service this will run as, for use in checking running and stopping");
-
-    @SetFromFlag("ansible.vars")
-    ConfigKey<Object> ANSIBLE_VARS = ConfigKeys.newConfigKey(Object.class, "brooklyn.ansible.vars",
-        "Ansible 'extra-vars' variable configuration values");
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
deleted file mode 100644
index a2c9676..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntity.java
+++ /dev/null
@@ -1,40 +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.cm.ansible;
-
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.core.annotation.Effector;
-import org.apache.brooklyn.core.annotation.EffectorParam;
-import org.apache.brooklyn.core.effector.MethodEffector;
-import org.apache.brooklyn.entity.software.base.SoftwareProcess;
-
-@ImplementedBy(AnsibleEntityImpl.class)
-public interface AnsibleEntity extends SoftwareProcess, AnsibleConfig {
-
-    MethodEffector<String> ANSIBLE_COMMAND = new MethodEffector<>(AnsibleEntity.class, "ansibleCommand");
-
-    @Effector(description = "Invoke an arbitrary Ansible command, optionally specifying the module (default is 'command')")
-    String ansibleCommand(
-        @EffectorParam(name="module", description = "Name of the Ansible module to invoke", defaultValue = "command")
-        String module,
-        @EffectorParam(name="args", description = "Arguments for the ansible command")
-        String args
-    );
-
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.java
deleted file mode 100644
index c2635ca..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityImpl.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.cm.ansible;
-
-import org.apache.brooklyn.entity.stock.EffectorStartableImpl;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
-import org.apache.brooklyn.util.text.Strings;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-public class AnsibleEntityImpl extends EffectorStartableImpl implements AnsibleEntity {
-
-    private AnsibleLifecycleEffectorTasks lifecycleTasks;
-
-    public void init() {
-        checkNotNull(getConfig(SERVICE_NAME), "service name is missing. it has to be provided by the user");
-        String playbookName = getConfig(ANSIBLE_PLAYBOOK);
-        if (!Strings.isBlank(playbookName)) setDefaultDisplayName(playbookName + " (ansible)");
-
-        super.init();
-
-        lifecycleTasks = new AnsibleLifecycleEffectorTasks();
-
-        lifecycleTasks.attachLifecycleEffectors(this);
-    }
-
-    @Override
-    public void populateServiceNotUpDiagnostics() {
-        // TODO no-op currently; should check ssh'able etc
-    }
-
-    @Override
-    public String ansibleCommand(String module, String args) {
-        final ProcessTaskWrapper<Integer> command = DynamicTasks.queue(
-            AnsiblePlaybookTasks.moduleCommand(module, config().get(ANSIBLE_VARS), lifecycleTasks.getRunDir(), args));
-        command.asTask().blockUntilEnded();
-        if (0 == command.getExitCode()) {
-            return command.getStdout();
-        } else {
-            throw new RuntimeException("Command (" + args + ") in module " + module
-                + " failed with stderr:\n" + command.getStderr() + "\n");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
deleted file mode 100644
index e1a8622..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsibleLifecycleEffectorTasks.java
+++ /dev/null
@@ -1,203 +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.cm.ansible;
-
-import com.google.common.base.Supplier;
-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.entity.trait.Startable;
-import org.apache.brooklyn.core.location.Locations;
-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.feed.ssh.SshFeed;
-import org.apache.brooklyn.feed.ssh.SshPollConfig;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.net.Urls;
-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;
-
-public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements AnsibleConfig {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AnsibleLifecycleEffectorTasks.class);
-
-    protected String serviceName;
-    protected SshFeed serviceSshFeed;
-
-    protected Object extraVars;
-    protected String baseDir;
-    protected String runDir;
-
-    public AnsibleLifecycleEffectorTasks() {
-    }
-
-    public String getServiceName() {
-        if (serviceName!=null) return serviceName;
-        return serviceName = entity().config().get(AnsibleConfig.SERVICE_NAME);
-    }
-
-    public Object getExtraVars() {
-        if (extraVars != null) return extraVars;
-        return extraVars = entity().config().get(ANSIBLE_VARS);
-    }
-
-    public String getBaseDir() {
-        if (null != baseDir) return baseDir;
-        return baseDir = MachineLifecycleEffectorTasks.resolveOnBoxDir(entity(),
-                Machines.findUniqueMachineLocation(entity().getLocations(), SshMachineLocation.class).get());
-    }
-
-    public String getRunDir() {
-        if (null != runDir) return runDir;
-        return runDir = Urls.mergePaths(getBaseDir(), "apps/"+entity().getApplicationId()+"/ansible/playbooks/"
-            +entity().getEntityType().getSimpleName()+"_"+entity().getId());
-    }
-
-    @Override
-    public void attachLifecycleEffectors(Entity entity) {
-        if (getServiceName()==null && getClass().equals(AnsibleLifecycleEffectorTasks.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);
-    }
-
-    @Override
-    protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
-        startWithAnsibleAsync();
-
-        return "ansible start tasks submitted";
-    }
-
-    protected String getPlaybookName() {
-        return entity().config().get(ANSIBLE_PLAYBOOK);
-    }
-
-    protected void startWithAnsibleAsync() {
-        String installDir = Urls.mergePaths(getBaseDir(), "installs/ansible");
-
-        String playbookUrl = entity().config().get(ANSIBLE_PLAYBOOK_URL);
-        String playbookYaml = entity().config().get(ANSIBLE_PLAYBOOK_YAML);
-
-        if (Strings.isNonBlank(playbookUrl) && Strings.isNonBlank(playbookYaml)) {
-            throw new IllegalArgumentException("You can specify " +  AnsibleConfig.ANSIBLE_PLAYBOOK_URL.getName()
-                +  " or " + AnsibleConfig.ANSIBLE_PLAYBOOK_YAML.getName() + " but not both of them!");
-        }
-
-        DynamicTasks.queue(AnsiblePlaybookTasks.installAnsible(installDir, false));
-
-        if (getExtraVars() != null) {
-            DynamicTasks.queue(AnsiblePlaybookTasks.configureExtraVars(getRunDir(), extraVars, false));
-        }
-
-        if (Strings.isNonBlank(playbookUrl)) {
-            DynamicTasks.queue(AnsiblePlaybookTasks.installPlaybook(getRunDir(), getPlaybookName(), playbookUrl));
-        }
-
-        if (Strings.isNonBlank(playbookYaml)) {
-            DynamicTasks.queue(AnsiblePlaybookTasks.buildPlaybookFile(getRunDir(), getPlaybookName()));
-        }
-        DynamicTasks.queue(AnsiblePlaybookTasks.runAnsible(getRunDir(), getExtraVars(), getPlaybookName()));
-    }
-
-
-    protected void postStartCustom() {
-        boolean result = false;
-        result |= tryCheckStartService();
-
-        if (!result) {
-            LOG.warn("No way to check whether "+entity()+" is running; assuming yes");
-        }
-        entity().sensors().set(SoftwareProcess.SERVICE_UP, true);
-        
-        Maybe<SshMachineLocation> machine = Locations.findUniqueSshMachineLocation(entity().getLocations());
-
-        if (machine.isPresent()) {
-            
-            String serviceName = String.format("[%s]%s", entity().config().get(SERVICE_NAME).substring(0, 1),
-                    entity().config().get(SERVICE_NAME).substring(1));
-            String checkCmd = String.format("ps -ef | grep %s", serviceName);
-
-            Integer serviceCheckPort = entity().config().get(ANSIBLE_SERVICE_CHECK_PORT);
-
-            if (serviceCheckPort != null) {
-                checkCmd = String.format("sudo ansible localhost -c local -m wait_for -a \"host=0.0.0.0 port=%d\"", serviceCheckPort);
-            }
-            serviceSshFeed = SshFeed.builder()
-                    .entity(entity())
-                    .period(Duration.ONE_MINUTE)
-                    .machine(machine.get())
-                    .poll(new SshPollConfig<Boolean>(Startable.SERVICE_UP)
-                            .command(checkCmd)
-                            .setOnSuccess(true)
-                            .setOnFailureOrException(false))
-                    .build();
-                    
-             entity().feeds().addFeed(serviceSshFeed);
-        } else {
-            LOG.warn("Location(s) {} not an ssh-machine location, so not polling for status; setting serviceUp immediately", entity().getLocations());
-        }
-    }
-
-    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(String.format(entity().config().get(AnsibleConfig.ANSIBLE_SERVICE_START), getServiceName()))).get())) {
-            throw new IllegalStateException("The process for "+entity()+" appears not to be running (service "+getServiceName()+")");
-        }
-
-        return true;
-    }
-
-    @Override
-    protected String stopProcessesAtMachine() {
-        boolean result = false;
-        result |= tryStopService();
-        if (!result) {
-            throw new IllegalStateException("The process for "+entity()+" could not be stopped (no impl!)");
-        }
-        return "stopped";
-    }
-
-    @Override
-    protected StopMachineDetails<Integer> stopAnyProvisionedMachines() {
-        return super.stopAnyProvisionedMachines();
-    }
-
-    protected boolean tryStopService() {
-        if (getServiceName()==null) return false;
-        int result = DynamicTasks.queue(SshEffectorTasks.ssh(String.format(entity().config().get(AnsibleConfig.ANSIBLE_SERVICE_STOP), getServiceName()))).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)");
-    }
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java
----------------------------------------------------------------------
diff --git a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java b/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.java
deleted file mode 100644
index 36076a1..0000000
--- a/software/cm/src/main/java/org/apache/brooklyn/entity/cm/ansible/AnsiblePlaybookTasks.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.cm.ansible;
-
-import org.apache.brooklyn.api.entity.Entity;
-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.core.ResourceUtils;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
-import org.apache.brooklyn.util.net.Urls;
-import org.apache.brooklyn.util.ssh.BashCommands;
-import org.apache.brooklyn.util.text.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.Yaml;
-
-import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
-
-public class AnsiblePlaybookTasks {
-    private static final Logger LOG = LoggerFactory.getLogger(AnsiblePlaybookTasks.class);
-    private static final String EXTRA_VARS_FILENAME = "extra_vars.yaml";
-
-    public static TaskFactory<?> installAnsible(String ansibleDirectory, boolean force) {
-        String installCmd = cdAndRun(ansibleDirectory, AnsibleBashCommands.INSTALL_ANSIBLE);
-        if (!force) installCmd = BashCommands.alternatives("which ansible", installCmd);
-        return SshEffectorTasks.ssh(installCmd).summary("install ansible");
-    }
-
-    public static TaskFactory<?> installPlaybook(final String ansibleDirectory, final String playbookName, final String playbookUrl) {
-        return Tasks.sequential("build ansible playbook file for "+playbookName,
-                SshEffectorTasks.put(ansibleDirectory + "/" + playbookName + ".yaml")
-                    .contents(ResourceUtils.create().getResourceFromUrl(playbookUrl))
-                    .createDirectory());
-    }
-    
-    protected static String cdAndRun(String targetDirectory, String command) {
-        return BashCommands.chain("mkdir -p "+targetDirectory,
-                "cd "+targetDirectory,
-                command);
-    }
-
-    public static TaskFactory<?> buildPlaybookFile(final String ansibleDirectory, String playbook) {
-        Entity entity = EffectorTasks.findEntity();
-        String yaml = entity.config().get(AnsibleConfig.ANSIBLE_PLAYBOOK_YAML);
-
-        return Tasks.sequential("build ansible playbook file for "+ playbook,
-            SshEffectorTasks.put(Urls.mergePaths(ansibleDirectory) + "/" + playbook + ".yaml")
-                .contents(yaml).createDirectory());
-    }
-
-    public static TaskFactory<?> runAnsible(final String dir, Object extraVars, String playbookName) {
-        String cmd = String.format("sudo ansible-playbook -i \"localhost,\" -c local "
-            + optionalExtraVarsParameter(extraVars)
-            + " -s %s.yaml", playbookName);
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Ansible command: {}", cmd);
-        }
-
-        return SshEffectorTasks.ssh(cdAndRun(dir, cmd)).
-                summary("run ansible playbook for " + playbookName).requiringExitCodeZero();
-    }
-
-    public static ProcessTaskFactory<Integer> moduleCommand(String module, Object extraVars, String root, String args) {
-        final String command = "ansible localhost "
-            + optionalExtraVarsParameter(extraVars)
-            + " -m '" + module + "' -a '" + args + "'";
-        return SshEffectorTasks.ssh(sudo(BashCommands.chain("cd " + root, command)))
-            .summary("ad-hoc: " + command).requiringExitCodeZero();
-    }
-
-    public static TaskFactory<?> configureExtraVars(String dir, Object extraVars, boolean force) {
-        DumperOptions options = new DumperOptions();
-        options.setDefaultScalarStyle(DumperOptions.ScalarStyle.DOUBLE_QUOTED);
-        Yaml asYaml = new Yaml(options);
-        final String varsYaml = asYaml.dump(extraVars);
-        return SshEffectorTasks.put(Urls.mergePaths(dir, EXTRA_VARS_FILENAME))
-            .contents(varsYaml)
-            .summary("install extra vars")
-            .createDirectory();
-    }
-
-    private static String optionalExtraVarsParameter(Object extraVars) {
-        if (null == extraVars || Strings.isBlank(extraVars.toString())) {
-            return "";
-        }
-        return " --extra-vars \"@" + EXTRA_VARS_FILENAME + "\" ";
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/c1a87838/software/cm/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/cm/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java b/software/cm/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
deleted file mode 100644
index 76e993d..0000000
--- a/software/cm/src/test/java/org/apache/brooklyn/entity/cm/ansible/AnsibleEntityIntegrationTest.java
+++ /dev/null
@@ -1,116 +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.cm.ansible;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.location.MachineDetails;
-import org.apache.brooklyn.api.location.OsDetails;
-import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.EntityAsserts;
-import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.location.BasicMachineDetails;
-import org.apache.brooklyn.core.test.entity.TestApplication;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-
-public class AnsibleEntityIntegrationTest {
-    protected TestApplication app;
-    protected LocalhostMachineProvisioningLocation testLocation;
-    protected AnsibleEntity ansible;
-    protected SshMachineLocation sshHost;
-
-    String playbookYaml = Joiner.on("\n").join(
-            "---",
-            "- hosts: localhost",
-            "  sudo: True",
-            "",
-            "  tasks:",
-            "  - apt: name=apache2 state=latest",
-            "    when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'",
-            "",
-            "  - yum: name=httpd state=latest",
-            "    when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'",
-            "",
-            "  - service: name=apache2 state=started enabled=no",
-            "    when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'",
-            "",
-            "  - service: name=httpd state=started enabled=no",
-            "    when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'");
-
-    @BeforeMethod(alwaysRun = true)
-    public void setup() throws Exception {
-        app = TestApplication.Factory.newManagedInstanceForTests();;
-        testLocation = new LocalhostMachineProvisioningLocation();
-        sshHost = testLocation.obtain();
-    }
-
-    @AfterMethod(alwaysRun = true)
-    public void shutdown() {
-        Entities.destroyAll(app.getManagementContext());
-    }
-    
-    @Test(groups = {"Integration"})
-    public void testAnsible() {
-        Task<BasicMachineDetails> detailsTask = app.getExecutionContext().submit(
-                BasicMachineDetails.taskForSshMachineLocation(sshHost));
-        MachineDetails machine = detailsTask.getUnchecked();
-
-
-        OsDetails details = machine.getOsDetails();
-        
-        String osName = details.getName();
-        String playbookServiceName = getPlaybookServiceName(osName);
-        ansible = app.createAndManageChild(EntitySpec.create(AnsibleEntity.class)
-                .configure("playbook.yaml", playbookYaml)
-                .configure("playbook", playbookServiceName)
-                .configure("service.name", playbookServiceName));
-
-        app.start(ImmutableList.of(testLocation));
-        EntityAsserts.assertAttributeEqualsEventually(ansible, Startable.SERVICE_UP, true);
-
-        ansible.stop();
-        EntityAsserts.assertAttributeEqualsEventually(ansible, Startable.SERVICE_UP, false);
-    }
-
-    private String getPlaybookServiceName(String os) {
-        String name;
-
-        switch (os.toLowerCase()) {
-            case "fedora":
-                name = "httpd";
-                break;
-            case "centos":
-                name = "httpd";
-                break;
-            default:
-                name = "apache2";
-        }
-        return name;
-    }
-}
-
-


Mime
View raw message