modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
| 78 ---------
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
| 68 ++++++++
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
| 2
modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
| 51 ++++++
modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
| 14 +
modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
| 2
modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
| 85 ++++++----
modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
| 17 ++
8 files changed, 208 insertions(+), 109 deletions(-)
New commits:
commit 31cdbfd2db0c5220319665482b41984419dd4cbc
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Mar 2 18:14:44 2010 -0500
add script recipe command
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
deleted file mode 100644
index 26d1b82..0000000
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ConfigdefRecipeCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also as published by the Free
- * Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.rhq.bundle.filetemplate.recipe;
-
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
-/**
- * @deprecated I think this command will not be used - probably should delete it
- * @author mazz
- */
-public class ConfigdefRecipeCommand implements RecipeCommand {
-
- public String getName() {
- return "configdef";
- }
-
- public void parse(RecipeContext context, String[] args) {
- String sopts = ":f:";
- LongOpt[] lopts = { new LongOpt("file", LongOpt.REQUIRED_ARGUMENT,
null, 'f') };
-
- String filename = null;
-
- Getopt getopt = new Getopt(context.toString(), args, sopts, lopts);
- int code;
-
- while ((code = getopt.getopt()) != -1) {
- switch (code) {
- case ':':
- case '?': {
- throw new IllegalArgumentException("Bad recipe argument.");
- }
-
- case 1: {
- throw new IllegalArgumentException("Bad recipe argument!");
- }
-
- case 'f': {
- filename = getopt.getOptarg();
- break;
- }
-
- default: {
- throw new IllegalArgumentException("Unexpected error in recipe
command");
- }
- }
- }
-
- if (filename == null) {
- throw new IllegalArgumentException("Missing the -f argument to indicate
what the config def filename is");
- }
-
- // TODO: what to do? can I delete this command entirely?
-
- return;
- }
-}
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
index 43f0df1..fb911f3 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeContext.java
@@ -23,8 +23,10 @@
package org.rhq.bundle.filetemplate.recipe;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -42,11 +44,13 @@ public class RecipeContext {
private final Map<String, String> deployFiles;
private final Set<String> replacementVariables;
private Configuration replacementVariableValues;
+ private final List<Script> scripts;
public RecipeContext(String recipe) {
this.recipe = recipe;
this.deployFiles = new HashMap<String, String>();
this.replacementVariables = new HashSet<String>();
+ this.scripts = new ArrayList<Script>();
}
/**
@@ -114,4 +118,68 @@ public class RecipeContext {
}
values.put(new PropertySimple(name, value));
}
+
+ /**
+ * Returns a set of all the names of scripts found in the recipe.
+ *
+ * @return script names
+ */
+ public Set<String> getScriptFiles() {
+ Set<String> scriptFiles = new HashSet<String>();
+ for (Script script : this.scripts) {
+ scriptFiles.add(script.getExecutable());
+ }
+ return scriptFiles;
+ }
+
+ /**
+ * Adds a script that the recipe wants invoked.
+ *
+ * @param exe the script executable
+ * @param exeArgs the arguments to pass to the script
+ */
+ public void addScript(String exe, List<String> exeArgs) {
+ this.scripts.add(new Script(exe, exeArgs));
+ }
+
+ class Script {
+ private final List<String> args;
+ private final String exe;
+
+ public Script(String exe, List<String> args) {
+ this.exe = exe;
+ this.args = args;
+ }
+
+ public String getExecutable() {
+ return exe;
+ }
+
+ public List<String> getArguments() {
+ return args;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder("RecipeContext:\n");
+ str.append("Recipe
Text:\n").append(getRecipe()).append("\n");
+ str.append("Deploy Files:
").append(getDeployFiles()).append("\n");
+ str.append("Replacement Vars:
").append(getReplacementVariables()).append("\n");
+
+ str.append("Replacement Values: ");
+ Configuration values = getReplacementVariableValues();
+ if (values == null) {
+ str.append("<none>");
+ } else {
+ str.append(values.getProperties());
+ }
+ str.append("\n");
+
+ str.append("Script Files:
").append(getScriptFiles()).append("\n");
+ for (Script script : this.scripts) {
+ str.append("* ").append(script.getExecutable()).append("
").append(script.getArguments()).append("\n");
+ }
+ return str.toString();
+ }
}
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
index f8db1c8..d18fd4b 100644
---
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/RecipeParser.java
@@ -119,7 +119,7 @@ public class RecipeParser {
protected HashMap<String, RecipeCommand> createRecipeCommands() {
HashMap<String, RecipeCommand> commands = new HashMap<String,
RecipeCommand>();
- RecipeCommand[] knownCommands = new RecipeCommand[] { new
ConfigdefRecipeCommand(), //
+ RecipeCommand[] knownCommands = new RecipeCommand[] { new ScriptRecipeCommand(),
//
new DeployRecipeCommand() //
};
diff --git
a/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
new file mode 100644
index 0000000..2173c06
--- /dev/null
+++
b/modules/common/filetemplate-bundle/src/main/java/org/rhq/bundle/filetemplate/recipe/ScriptRecipeCommand.java
@@ -0,0 +1,51 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2010 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.bundle.filetemplate.recipe;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ScriptRecipeCommand implements RecipeCommand {
+
+ public String getName() {
+ return "script";
+ }
+
+ public void parse(RecipeContext context, String[] args) {
+
+ if (args == null || args.length == 0) {
+ throw new IllegalArgumentException("Missing the script command to
execute");
+ }
+
+ String exe = args[0];
+ List<String> exeArgs = new ArrayList<String>(args.length - 1);
+ for (int i = 1; i < args.length; i++) {
+ exeArgs.add(args[i]);
+ }
+
+ context.addScript(exe, exeArgs);
+
+ return;
+ }
+}
diff --git
a/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
b/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
index b2efdaf..40bc7fb 100644
---
a/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
+++
b/modules/common/filetemplate-bundle/src/test/java/org/rhq/bundle/filetemplate/recipe/RecipeParserTest.java
@@ -24,6 +24,7 @@
package org.rhq.bundle.filetemplate.recipe;
import java.util.Map;
+import java.util.Set;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -39,6 +40,19 @@ public class RecipeParserTest {
cleanRecipe();
}
+ public void testScriptRecipe() throws Exception {
+ addRecipeCommand("script run-me.sh");
+ addRecipeCommand("script lots-o-params.sh -d /opt/jboss -- foo.txt
\"hello world\"");
+ addRecipeCommand("script run-me.sh with params");
+ RecipeParser parser = new RecipeParser();
+ RecipeContext context = new RecipeContext(getRecipe());
+ parser.parseRecipe(context);
+ Set<String> scripts = context.getScriptFiles();
+ assert scripts.size() == 2 : scripts;
+ assert scripts.contains("run-me.sh") : scripts;
+ assert scripts.contains("lots-o-params.sh") : scripts;
+ }
+
public void testSimpleRecipeReplacementVariables() throws Exception {
addRecipeCommand("# <% ignored.inside.comment %>");
addRecipeCommand("deploy -f jboss.tar -d \"<% opt.dir
%>/jboss\"");
diff --git
a/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
b/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
index 34902c0..99b8504 100644
---
a/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
+++
b/modules/enterprise/server/plugins/filetemplate-bundle/src/main/java/org/rhq/enterprise/server/plugins/filetemplate/BundleServerPluginComponent.java
@@ -76,6 +76,8 @@ public class BundleServerPluginComponent implements
ServerPluginComponent, Bundl
Set<String> bundleFileNames = new HashSet<String>();
Map<String, String> deployFiles = recipeContext.getDeployFiles();
bundleFileNames.addAll(deployFiles.keySet());
+ Set<String> scriptFiles = recipeContext.getScriptFiles();
+ bundleFileNames.addAll(scriptFiles);
ConfigurationDefinition configDef = null;
if (recipeContext.getReplacementVariables() != null) {
diff --git
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
index 7f76757..cee69db 100644
---
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
+++
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
@@ -75,42 +75,25 @@ public class FileTemplateBundlePluginServerComponent implements
ResourceComponen
List<PackageVersion> packageVersions =
bundleManager.getAllBundleVersionPackageVersions(bundleVersion);
for (PackageVersion packageVersion : packageVersions) {
File packageFile = new File(tmpDir, packageVersion.getFileName());
- packageFile.getParentFile().mkdirs();
- FileOutputStream fos = new FileOutputStream(packageFile);
- try {
- long size = bundleManager.getFileContent(packageVersion, fos);
- if (packageVersion.getFileSize() != null && size !=
packageVersion.getFileSize().longValue()) {
- log.warn("Downloaded bundle file [" + packageVersion +
"] but its size was [" + size
- + "] when it was expected to be [" +
packageVersion.getFileSize() + "].");
- }
- } finally {
- fos.close();
- }
- // verify the content
- if (packageVersion.getMD5() != null) {
- String realMD5 =
MessageDigestGenerator.getDigestString(packageFile);
- if (!packageVersion.getMD5().equals(realMD5)) {
- throw new Exception("Package version [" +
packageVersion + "] failed MD5 check. expected=["
- + packageVersion.getMD5() + "], actual=[" + realMD5
+ "]");
- }
- } else if (packageVersion.getSHA256() != null) {
- FileInputStream is = new FileInputStream(packageFile);
+ try {
+ verifyHash(packageVersion, packageFile);
+ } catch (Exception e) {
+ // file either doesn't exist or it hash doesn't match,
download a new copy
+ packageFile.getParentFile().mkdirs();
+ FileOutputStream fos = new FileOutputStream(packageFile);
try {
- MessageDigestGenerator gen = new
MessageDigestGenerator("SHA256");
- gen.add(is);
- String realSHA256 = gen.getDigestString();
- if (!packageVersion.getSHA256().equals(realSHA256)) {
- throw new Exception("Package version [" +
packageVersion
- + "] failed SHA256 check. expected=[" +
packageVersion.getSHA256() + "], actual=["
- + realSHA256 + "]");
+ long size = bundleManager.getFileContent(packageVersion, fos);
+ if (packageVersion.getFileSize() != null && size !=
packageVersion.getFileSize().longValue()) {
+ log.warn("Downloaded bundle file [" +
packageVersion + "] but its size was [" + size
+ + "] when it was expected to be [" +
packageVersion.getFileSize() + "].");
}
} finally {
- is.close();
+ fos.close();
}
- } else {
- log.debug("Package version [" + packageVersion + "]
has no MD5/SHA256 hash - not verifying it");
+ // now try to verify it again, if this throws an exception, that is
very bad and we need to abort
+ verifyHash(packageVersion, packageFile);
}
packageVersionFiles.put(packageVersion, packageFile);
@@ -131,4 +114,46 @@ public class FileTemplateBundlePluginServerComponent implements
ResourceComponen
}
return result;
}
+
+ /**
+ * Checks to see if the package file's hash matches that of the given package
version.
+ * If the file doesn't exist or the hash doesn't match, an exception is
thrown.
+ * This method returns normally if the hash matches the file.
+ * If there is no known hash in the package version, this method returns normally.
+ *
+ * @param packageVersion contains the hash that is expected
+ * @param packageFile the local file whose hash is to be checked
+ * @throws Exception if the file does not match the hash or the file doesn't
exist
+ */
+ private void verifyHash(PackageVersion packageVersion, File packageFile) throws
Exception {
+ if (!packageFile.exists()) {
+ throw new Exception("Package version [" + packageVersion + "]
does not exist, cannot check hash");
+ }
+
+ if (packageVersion.getMD5() != null) {
+ String realMD5 = MessageDigestGenerator.getDigestString(packageFile);
+ if (!packageVersion.getMD5().equals(realMD5)) {
+ throw new Exception("Package version [" + packageVersion +
"] failed MD5 check. expected=["
+ + packageVersion.getMD5() + "], actual=[" + realMD5 +
"]");
+ }
+ } else if (packageVersion.getSHA256() != null) {
+ FileInputStream is = new FileInputStream(packageFile);
+ try {
+ MessageDigestGenerator gen = new
MessageDigestGenerator("SHA256");
+ gen.add(is);
+ String realSHA256 = gen.getDigestString();
+ if (!packageVersion.getSHA256().equals(realSHA256)) {
+ throw new Exception("Package version [" + packageVersion +
"] failed SHA256 check. expected=["
+ + packageVersion.getSHA256() + "], actual=[" +
realSHA256 + "]");
+ }
+ } finally {
+ is.close();
+ }
+
+ } else {
+ log.debug("Package version [" + packageVersion + "] has no
MD5/SHA256 hash - not verifying it");
+ }
+
+ return;
+ }
}
diff --git
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
index 1dbad78..2e0d1dc 100644
---
a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
+++
b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/ProcessingRecipeContext.java
@@ -80,6 +80,23 @@ public class ProcessingRecipeContext extends RecipeContext {
super.addReplacementVariables(replacementVariables);
}
+ @Override
+ public void addScript(String exe, List<String> exeArgs) {
+ super.addScript(exe, exeArgs);
+
+ File scriptFile = new File(this.baseWorkingDirectory, exe);
+
+ ProcessExecution pe = new ProcessExecution(scriptFile.getAbsolutePath());
+ pe.setArguments(exeArgs);
+ pe.setWaitForCompletion(30 * 60 * 1000L);
+ pe.setWorkingDirectory(scriptFile.getParent());
+
+ ProcessExecutionResults results = this.systemInfo.executeProcess(pe);
+ if (results.getError() != null) {
+ throw new RuntimeException("Could not execute script [" + pe +
"]: " + results, results.getError());
+ }
+ }
+
private ProcessExecution getUnzipExecution(String filename, String directory) {
String exe;
List<String> args = null;