brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rich...@apache.org
Subject [03/21] git commit: Added initial SaltStack classes, based on existing Chef code
Date Wed, 28 May 2014 16:05:19 GMT
Added initial SaltStack classes, based on existing Chef code


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

Branch: refs/heads/master
Commit: e2a93f4231217cdc98bbe181560c54472b9270e6
Parents: 4e1301b
Author: Andrew Kennedy <andrew.kennedy@cloudsoftcorp.com>
Authored: Tue Oct 22 15:13:33 2013 +0100
Committer: Andrew Kennedy <andrew.kennedy@cloudsoftcorp.com>
Committed: Wed May 28 15:06:18 2014 +0100

----------------------------------------------------------------------
 .../brooklyn/entity/salt/SaltBashCommands.java  | 83 +++++++++++++++++++
 .../java/brooklyn/entity/salt/SaltTasks.java    | 86 ++++++++++++++++++++
 2 files changed, 169 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2a93f42/software/base/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/salt/SaltBashCommands.java b/software/base/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
new file mode 100644
index 0000000..6930113
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/salt/SaltBashCommands.java
@@ -0,0 +1,83 @@
+package brooklyn.entity.salt;
+
+import static brooklyn.util.ssh.BashCommands.INSTALL_CURL;
+import static brooklyn.util.ssh.BashCommands.INSTALL_TAR;
+import static brooklyn.util.ssh.BashCommands.INSTALL_UNZIP;
+import static brooklyn.util.ssh.BashCommands.downloadToStdout;
+import static brooklyn.util.ssh.BashCommands.sudo;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.io.FilenameUtils;
+
+import brooklyn.entity.chef.ChefBashCommands;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.io.Files;
+
+/**
+ * BASH commands useful for setting up SaltStack.
+ *
+ * @see ChefBashCommands
+ */
+@Beta
+public class SaltBashCommands {
+
+    // TODO inject the version number tag
+    public static final String INSTALL_USING_SALTSTACK_BOOSTRAP =
+            BashCommands.chain(
+                    INSTALL_CURL,
+                    INSTALL_TAR,
+                    INSTALL_UNZIP,
+                    "( "+downloadToStdout("http://bootstrap.saltstack.org/") + " | " + sudo("sudo
sh -s -- -M -N git stable")+" )");
+
+    /**
+     * SaltStack formulas are normally found at https://github.com/saltstack-formulas as
repositories.
+     * 
+     * this assumes the download is an archive containing a single directory on the root
which will be renamed to "cookbookName";
+     * if that directory already has the correct name cookbookName can be null,
+     * but if e.g. taking from a github tarball it will typically be of the form cookbookName-master/

+     * hence the renaming.
+     */
+    // TODO support installing from classpath, and using the repository (tie in with those
methods)
+    public static final String downloadAndExpandFormula(String source, @Nullable String formulaName,
boolean force) {
+        String dl = downloadAndExpandFormula(source);
+        if (formulaName==null) return dl;
+        String tmpName = "tmp-"+Strings.makeValidFilename(formulaName)+"-"+Identifiers.makeRandomId(4);
+        String installCmd = BashCommands.chain("mkdir "+tmpName, "cd "+tmpName, dl, 
+                BashCommands.requireTest("`ls | wc -w` -eq 1", 
+                        "The downloaded archive must contain exactly one directory; contained"),
+                "FORMULA_EXPANDED_DIR=`ls`",
+                "mv $FORMULA_EXPANDED_DIR '../"+formulaName+"'",
+                "cd ..",
+                "rm -rf "+tmpName);
+        if (!force) return BashCommands.alternatives("ls "+formulaName, installCmd);
+        else return BashCommands.alternatives("rm -rf "+formulaName, installCmd);
+    }
+    
+    /** as {@link #downloadAndExpandFormula(String, String)} with no formula name */
+    public static final String downloadAndExpandFormula(String source) {
+//        curl -f -L  https://github.com/saltstack-formulas/nginx-formula/archive/master.tar.gz
| tar xvz
+        String ext = Files.getFileExtension(source);
+        if ("tar".equalsIgnoreCase(ext))
+            return downloadToStdout(source) + " | tar xv";
+        if ("tgz".equalsIgnoreCase(ext) || source.toLowerCase().endsWith(".tar.gz"))
+            return downloadToStdout(source) + " | tar xvz";
+        
+        String target = FilenameUtils.getName(source);
+        if (target==null) target = ""; else target = target.trim();
+        target += "_"+Strings.makeRandomId(4);
+        
+        if ("zip".equalsIgnoreCase(ext) || "tar.gz".equalsIgnoreCase(ext))
+            return BashCommands.chain(
+                BashCommands.commandToDownloadUrlAs(source, target), 
+                "unzip "+target,
+                "rm "+target);
+        
+        throw new UnsupportedOperationException("No way to expand "+source+" (yet)");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2a93f42/software/base/src/main/java/brooklyn/entity/salt/SaltTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/salt/SaltTasks.java b/software/base/src/main/java/brooklyn/entity/salt/SaltTasks.java
new file mode 100644
index 0000000..de43b36
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/salt/SaltTasks.java
@@ -0,0 +1,86 @@
+package brooklyn.entity.salt;
+
+import java.util.Map;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.entity.software.SshEffectorTasks;
+import brooklyn.management.TaskFactory;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Urls;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.Tasks;
+
+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 SaltTasks {
+
+    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().name("install cookbooks").body(
+                new Runnable() {
+                    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(String chefDirectory, String cookbook,
String url, boolean force) {
+        // TODO if it's server, try knife first
+        // TODO support downloads from classpath / local server
+        return SshEffectorTasks.ssh(cdAndRun(chefDirectory, ChefBashCommands.downloadAndExpandCookbook(url,
cookbook, force))).
+                summary("install cookbook "+cookbook).requiringExitCodeZero();
+    }
+
+    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 = File.absolute_path(File.dirname(__FILE__))\n"+
+                "\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();
+    }
+    
+}


Mime
View raw message