Addition of Ansible extra vars from Brooklyn config.
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-library/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-library/commit/121db325 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-library/tree/121db325 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-library/diff/121db325 Branch: refs/heads/master Commit: 121db3252a606aebdd9fc7a038f9920f082fdd8a Parents: 8de0e9f Author: Geoff Macartney <[email protected]> Authored: Wed Feb 10 14:44:54 2016 +0000 Committer: Yavor Yanchev <[email protected]> Committed: Wed Feb 17 11:43:03 2016 +0200 ---------------------------------------------------------------------- .../entity/cm/ansible/AnsibleConfig.java | 20 ++++---- .../entity/cm/ansible/AnsibleEntityImpl.java | 24 ++++++---- .../ansible/AnsibleLifecycleEffectorTasks.java | 49 ++++++++++++++------ .../entity/cm/ansible/AnsiblePlaybookTasks.java | 47 +++++++++++++++---- 4 files changed, 100 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/121db325/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 index b201294..d63c2c6 100644 --- 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 @@ -28,35 +28,39 @@ import com.google.common.annotations.Beta; @Beta public interface AnsibleConfig { - public static enum AnsibleModes { + enum AnsibleModes { PLAYBOOK }; @SetFromFlag("playbook") - public static final ConfigKey<String> ANSIBLE_PLAYBOOK = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbook", + ConfigKey<String> ANSIBLE_PLAYBOOK = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbook", "Playbook to be execute by Ansible"); @SetFromFlag("playbook.yaml") - public static final ConfigKey<String> ANSIBLE_PLAYBOOK_YAML = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookYaml", + ConfigKey<String> ANSIBLE_PLAYBOOK_YAML = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookYaml", "Playbook to be execute by Ansible"); @SetFromFlag("playbook.url") - public static final ConfigKey<String> ANSIBLE_PLAYBOOK_URL = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookUrl"); + ConfigKey<String> ANSIBLE_PLAYBOOK_URL = ConfigKeys.newStringConfigKey("brooklyn.ansible.playbookUrl"); @SetFromFlag("ansible.service.start") - public static final ConfigKey<String> ANSIBLE_SERVICE_START = ConfigKeys.newStringConfigKey("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") - public static final ConfigKey<String> ANSIBLE_SERVICE_STOP = ConfigKeys.newStringConfigKey("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") - public static final ConfigKey<Integer> ANSIBLE_SERVICE_CHECK_PORT = ConfigKeys.newIntegerConfigKey("ansible.service.check.port"); + ConfigKey<Integer> ANSIBLE_SERVICE_CHECK_PORT = ConfigKeys.newIntegerConfigKey("ansible.service.check.port"); @SetFromFlag("service.name") - public static final ConfigKey<String> SERVICE_NAME = ConfigKeys.newStringConfigKey("brooklyn.ansible.serviceName", + 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/121db325/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 index b34603e..c2635ca 100644 --- 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 @@ -27,13 +27,18 @@ 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(); - new AnsibleLifecycleEffectorTasks().attachLifecycleEffectors(this); + + lifecycleTasks = new AnsibleLifecycleEffectorTasks(); + + lifecycleTasks.attachLifecycleEffectors(this); } @Override @@ -43,13 +48,14 @@ public class AnsibleEntityImpl extends EffectorStartableImpl implements AnsibleE @Override public String ansibleCommand(String module, String args) { - final ProcessTaskWrapper<Integer> command = DynamicTasks.queue(AnsiblePlaybookTasks.moduleCommand(module, 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"); - } + 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/121db325/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 index 0262af3..e1a8622 100644 --- 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 @@ -18,6 +18,7 @@ */ 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; @@ -31,16 +32,14 @@ import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffect import org.apache.brooklyn.feed.ssh.SshFeed; import org.apache.brooklyn.feed.ssh.SshPollConfig; import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; 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 com.google.common.base.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks implements AnsibleConfig { @@ -48,7 +47,11 @@ public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks protected String serviceName; protected SshFeed serviceSshFeed; - + + protected Object extraVars; + protected String baseDir; + protected String runDir; + public AnsibleLifecycleEffectorTasks() { } @@ -57,6 +60,23 @@ public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks 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)) { @@ -79,30 +99,33 @@ public class AnsibleLifecycleEffectorTasks extends MachineLifecycleEffectorTasks } protected void startWithAnsibleAsync() { - String baseDir = MachineLifecycleEffectorTasks.resolveOnBoxDir(entity(), Machines.findUniqueMachineLocation(entity().getLocations(), SshMachineLocation.class).get()); - String installDir = Urls.mergePaths(baseDir, "installs/ansible"); + 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!"); + 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)); - String runDir = Urls.mergePaths(baseDir, "apps/"+entity().getApplicationId()+"/ansible/playbooks/"+entity().getEntityType().getSimpleName()+"_"+entity().getId()); - + if (getExtraVars() != null) { + DynamicTasks.queue(AnsiblePlaybookTasks.configureExtraVars(getRunDir(), extraVars, false)); + } + if (Strings.isNonBlank(playbookUrl)) { - DynamicTasks.queue(AnsiblePlaybookTasks.installPlaybook(runDir, getPlaybookName(), playbookUrl)); + DynamicTasks.queue(AnsiblePlaybookTasks.installPlaybook(getRunDir(), getPlaybookName(), playbookUrl)); } if (Strings.isNonBlank(playbookYaml)) { - DynamicTasks.queue(AnsiblePlaybookTasks.buildPlaybookFile(runDir, getPlaybookName())); + DynamicTasks.queue(AnsiblePlaybookTasks.buildPlaybookFile(getRunDir(), getPlaybookName())); } - DynamicTasks.queue(AnsiblePlaybookTasks.runAnsible(runDir, getPlaybookName())); + DynamicTasks.queue(AnsiblePlaybookTasks.runAnsible(getRunDir(), getExtraVars(), getPlaybookName())); } + protected void postStartCustom() { boolean result = false; result |= tryCheckStartService(); http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/121db325/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 index 29924d4..36076a1 100644 --- 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 @@ -27,15 +27,17 @@ 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 java.util.Map; +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); @@ -45,7 +47,9 @@ public class AnsiblePlaybookTasks { 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()); + SshEffectorTasks.put(ansibleDirectory + "/" + playbookName + ".yaml") + .contents(ResourceUtils.create().getResourceFromUrl(playbookUrl)) + .createDirectory()); } protected static String cdAndRun(String targetDirectory, String command) { @@ -59,24 +63,47 @@ public class AnsiblePlaybookTasks { 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()); + SshEffectorTasks.put(Urls.mergePaths(ansibleDirectory) + "/" + playbook + ".yaml") + .contents(yaml).createDirectory()); } - public static TaskFactory<?> runAnsible(final String ansibleDirectory, String playbookName) { - String cmd = String.format("sudo ansible-playbook -i \"localhost,\" -c local -s %s.yaml", playbookName); + 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(ansibleDirectory, cmd)). + return SshEffectorTasks.ssh(cdAndRun(dir, cmd)). summary("run ansible playbook for " + playbookName).requiringExitCodeZero(); } - public static ProcessTaskFactory<Integer> moduleCommand(String module, String args) { - final String command = "ansible localhost -m '" + module + "' -a '" + args + "'"; - return SshEffectorTasks.ssh(sudo(command)) + 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 + "\" "; + } }
