mirror of https://github.com/apache/jclouds.git
Issue 126: added initializers and positional parameter converters
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2344 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
d43c31f1fd
commit
fbf9225f5d
|
@ -25,6 +25,7 @@ package org.jclouds.initbuilder;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
@ -33,6 +34,9 @@ import org.jclouds.initbuilder.domain.ShellToken;
|
||||||
import org.jclouds.initbuilder.util.Utils;
|
import org.jclouds.initbuilder.util.Utils;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +52,9 @@ public class InitBuilder {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Map<String, String> variables = Maps.newHashMap();
|
Map<String, String> variables = Maps.newHashMap();
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
List<String> variablesToUnset = Lists.newArrayList("path", "javaHome", "libraryPath");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a switch statement to the script. If its value is found, it will invoke the corresponding
|
* Adds a switch statement to the script. If its value is found, it will invoke the corresponding
|
||||||
* action.
|
* action.
|
||||||
|
@ -73,6 +80,14 @@ public class InitBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsets a variable to ensure it is set within the script.
|
||||||
|
*/
|
||||||
|
public InitBuilder unsetEnvironmentVariable(String name) {
|
||||||
|
variablesToUnset.add(checkNotNull(name, "name"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports a variable inside the script
|
* Exports a variable inside the script
|
||||||
*/
|
*/
|
||||||
|
@ -92,15 +107,26 @@ public class InitBuilder {
|
||||||
* @param osFamily
|
* @param osFamily
|
||||||
* whether to write a cmd or bash script.
|
* whether to write a cmd or bash script.
|
||||||
*/
|
*/
|
||||||
public String build(OsFamily osFamily) {
|
public String build(final OsFamily osFamily) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(ShellToken.SHEBANG.to(osFamily));
|
builder.append(ShellToken.SHEBANG.to(osFamily));
|
||||||
builder.append(ShellToken.ZERO_PATH.to(osFamily));
|
builder.append(Utils.writeUnsetVariables(Lists.newArrayList(Iterables.transform(
|
||||||
|
variablesToUnset, new Function<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
if (ShellToken.tokenValueMap(osFamily).containsKey(from + "Variable"))
|
||||||
|
return Utils.FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL.apply(ShellToken
|
||||||
|
.tokenValueMap(osFamily).get(from + "Variable"));
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
})), osFamily));
|
||||||
|
builder.append(Utils.writeZeroPath(osFamily));
|
||||||
builder.append(Utils.writeVariableExporters(variables, osFamily));
|
builder.append(Utils.writeVariableExporters(variables, osFamily));
|
||||||
for (Entry<String, Map<String, String>> entry : switchExec.entrySet()) {
|
for (Entry<String, Map<String, String>> entry : switchExec.entrySet()) {
|
||||||
builder.append(Utils.writeSwitch(entry.getKey(), entry.getValue(), osFamily));
|
builder.append(Utils.writeSwitch(entry.getKey(), entry.getValue(), osFamily));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,13 +33,13 @@ import com.google.common.collect.MapMaker;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants used in operating suy
|
* Constants used in shell scripting.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public enum ShellToken {
|
public enum ShellToken {
|
||||||
|
|
||||||
FS, PS, LF, SH, SOURCE, REM, ARGS, VARSTART, VAREND, SHEBANG, ZERO_PATH, EXE;
|
FS, PS, LF, SH, SOURCE, REM, ARGS, VARSTART, VAREND, SHEBANG, LIBRARY_PATH_VARIABLE;
|
||||||
|
|
||||||
private static final Map<OsFamily, Map<String, String>> familyToTokenValueMap = new MapMaker()
|
private static final Map<OsFamily, Map<String, String>> familyToTokenValueMap = new MapMaker()
|
||||||
.makeComputingMap(new Function<OsFamily, Map<String, String>>() {
|
.makeComputingMap(new Function<OsFamily, Map<String, String>>() {
|
||||||
|
@ -91,6 +91,13 @@ public enum ShellToken {
|
||||||
case UNIX:
|
case UNIX:
|
||||||
return "bash";
|
return "bash";
|
||||||
}
|
}
|
||||||
|
case LIBRARY_PATH_VARIABLE:
|
||||||
|
switch (family) {
|
||||||
|
case WINDOWS:
|
||||||
|
return "PATH";
|
||||||
|
case UNIX:
|
||||||
|
return "LD_LIBRARY_PATH";
|
||||||
|
}
|
||||||
case SOURCE:
|
case SOURCE:
|
||||||
switch (family) {
|
switch (family) {
|
||||||
case WINDOWS:
|
case WINDOWS:
|
||||||
|
@ -133,20 +140,7 @@ public enum ShellToken {
|
||||||
case UNIX:
|
case UNIX:
|
||||||
return "#!/bin/bash\n";
|
return "#!/bin/bash\n";
|
||||||
}
|
}
|
||||||
case ZERO_PATH:
|
|
||||||
switch (family) {
|
|
||||||
case WINDOWS:
|
|
||||||
return "set PATH=c:\\windows\\;C:\\windows\\system32\r\n";
|
|
||||||
case UNIX:
|
|
||||||
return "export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin\n";
|
|
||||||
}
|
|
||||||
case EXE:
|
|
||||||
switch (family) {
|
|
||||||
case WINDOWS:
|
|
||||||
return ".exe";
|
|
||||||
case UNIX:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("token " + this + " not configured");
|
throw new UnsupportedOperationException("token " + this + " not configured");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.initbuilder.util;
|
package org.jclouds.initbuilder.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -31,7 +32,10 @@ import java.util.regex.Pattern;
|
||||||
import org.jclouds.initbuilder.domain.OsFamily;
|
import org.jclouds.initbuilder.domain.OsFamily;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities used to build init scripts.
|
* Utilities used to build init scripts.
|
||||||
|
@ -40,7 +44,25 @@ import com.google.common.collect.ImmutableMap;
|
||||||
*/
|
*/
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
public static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
|
public static final LowerCamelToUpperUnderscore FUNCTION_LOWER_CAMEL_TO_UPPER_UNDERSCORE = new LowerCamelToUpperUnderscore();
|
||||||
|
|
||||||
|
public static final class LowerCamelToUpperUnderscore implements Function<String, String> {
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final UpperUnderscoreToLowerCamel FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL = new UpperUnderscoreToLowerCamel();
|
||||||
|
|
||||||
|
public static final class UpperUnderscoreToLowerCamel implements Function<String, String> {
|
||||||
|
@Override
|
||||||
|
public String apply(String from) {
|
||||||
|
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replaces tokens that are expressed as <code>{token}</code>
|
* replaces tokens that are expressed as <code>{token}</code>
|
||||||
|
@ -98,6 +120,70 @@ public class Utils {
|
||||||
return initializers.toString();
|
return initializers.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Map<OsFamily, String> OS_TO_POSITIONAL_VAR_PATTERN = ImmutableMap.of(
|
||||||
|
OsFamily.UNIX, "set {key}=$1\nshift\n", OsFamily.WINDOWS, "set {key}=%1\r\nshift\r\n");
|
||||||
|
|
||||||
|
public static final Map<OsFamily, String> OS_TO_LOCAL_VAR_PATTERN = ImmutableMap.of(
|
||||||
|
OsFamily.UNIX, "set {key}=\"{value}\"\n", OsFamily.WINDOWS, "set {key}={value}\r\n");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an initialization statement for use inside a script or a function.
|
||||||
|
*
|
||||||
|
* @param positionalVariablesInLowerCamelCase
|
||||||
|
* - transfer the value of args into these statements. Note that there is no check to
|
||||||
|
* ensure that all source args are indeed present.
|
||||||
|
*/
|
||||||
|
public static String writePositionalVars(List<String> positionalVariablesInLowerCamelCase,
|
||||||
|
OsFamily family) {
|
||||||
|
StringBuilder initializers = new StringBuilder();
|
||||||
|
for (String variableInLowerCamelCase : positionalVariablesInLowerCamelCase) {
|
||||||
|
String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
|
||||||
|
variableInLowerCamelCase);
|
||||||
|
initializers.append(replaceTokens(OS_TO_POSITIONAL_VAR_PATTERN.get(family), ImmutableMap
|
||||||
|
.of("key", key)));
|
||||||
|
}
|
||||||
|
return initializers.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that variables come from a known source instead of bleeding in from a profile
|
||||||
|
*
|
||||||
|
* @param variablesInLowerCamelCase
|
||||||
|
* - System variables to unset
|
||||||
|
*/
|
||||||
|
public static String writeUnsetVariables(List<String> variablesInLowerCamelCase, OsFamily family) {
|
||||||
|
switch (family) {
|
||||||
|
case UNIX:
|
||||||
|
return String.format("unset %s\n", Joiner.on(' ').join(
|
||||||
|
Iterables.transform(variablesInLowerCamelCase,
|
||||||
|
FUNCTION_LOWER_CAMEL_TO_UPPER_UNDERSCORE)));
|
||||||
|
case WINDOWS:
|
||||||
|
StringBuilder initializers = new StringBuilder();
|
||||||
|
for (String variableInLowerCamelCase : variablesInLowerCamelCase) {
|
||||||
|
String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
|
||||||
|
variableInLowerCamelCase);
|
||||||
|
initializers.append(replaceTokens(OS_TO_LOCAL_VAR_PATTERN.get(family), ImmutableMap
|
||||||
|
.of("key", key, "value", "")));
|
||||||
|
}
|
||||||
|
return initializers.toString();
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("unsupported os: " + family);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Map<OsFamily, String> OS_TO_ZERO_PATH = ImmutableMap.of(OsFamily.WINDOWS,
|
||||||
|
"set PATH=c:\\windows\\;C:\\windows\\system32\r\n", OsFamily.UNIX,
|
||||||
|
"export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin\n");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return line used to zero out the path of the script such that basic commands such as unix ps
|
||||||
|
* will work.
|
||||||
|
*/
|
||||||
|
public static String writeZeroPath(OsFamily family) {
|
||||||
|
return OS_TO_ZERO_PATH.get(family);
|
||||||
|
}
|
||||||
|
|
||||||
public static final Map<OsFamily, String> OS_TO_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX,
|
public static final Map<OsFamily, String> OS_TO_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX,
|
||||||
"case ${variable} in\n", OsFamily.WINDOWS, "goto CASE%{variable}\r\n");
|
"case ${variable} in\n", OsFamily.WINDOWS, "goto CASE%{variable}\r\n");
|
||||||
|
|
||||||
|
@ -108,6 +194,25 @@ public class Utils {
|
||||||
"{value})\n {action}\n ;;\n", OsFamily.WINDOWS,
|
"{value})\n {action}\n ;;\n", OsFamily.WINDOWS,
|
||||||
":CASE_{value}\r\n {action}\r\n GOTO END_SWITCH\r\n");
|
":CASE_{value}\r\n {action}\r\n GOTO END_SWITCH\r\n");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a switch statement based on {@code variable}. If its value is found to be a key in
|
||||||
|
* {@code valueToActions}, the corresponding action is invoked.
|
||||||
|
*
|
||||||
|
* <p/>
|
||||||
|
* Ex. variable is {@code 1} - the first argument to the script<br/>
|
||||||
|
* and valueToActions is {"start" -> "echo hello", "stop" -> "echo goodbye"}<br/>
|
||||||
|
* the script created will respond accordingly:<br/>
|
||||||
|
* {@code ./script start }<br/>
|
||||||
|
* << returns hello<br/>
|
||||||
|
* {@code ./script stop }<br/>
|
||||||
|
* << returns goodbye<br/>
|
||||||
|
*
|
||||||
|
* @param variable
|
||||||
|
* - shell variable to switch on
|
||||||
|
* @param valueToActions
|
||||||
|
* - case statements, if the value of the variable matches a key, the corresponding
|
||||||
|
* value will be invoked.
|
||||||
|
*/
|
||||||
public static String writeSwitch(String variable, Map<String, String> valueToActions,
|
public static String writeSwitch(String variable, Map<String, String> valueToActions,
|
||||||
OsFamily family) {
|
OsFamily family) {
|
||||||
StringBuilder switchClause = new StringBuilder();
|
StringBuilder switchClause = new StringBuilder();
|
||||||
|
|
|
@ -40,9 +40,8 @@ public class ShellTokenTest {
|
||||||
public void testTokenValueMapUNIX() {
|
public void testTokenValueMapUNIX() {
|
||||||
Map<String, String> expected = new ImmutableMap.Builder<String, String>().put("fs", "/").put(
|
Map<String, String> expected = new ImmutableMap.Builder<String, String>().put("fs", "/").put(
|
||||||
"ps", ":").put("lf", "\n").put("sh", "bash").put("source", ".").put("rem", "#").put(
|
"ps", ":").put("lf", "\n").put("sh", "bash").put("source", ".").put("rem", "#").put(
|
||||||
"args", "$@").put("varstart", "$").put("varend", "").put("shebang", "#!/bin/bash\n")
|
"args", "$@").put("varstart", "$").put("varend", "").put("libraryPathVariable",
|
||||||
.put("zeroPath", "export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin\n")
|
"LD_LIBRARY_PATH").put("shebang", "#!/bin/bash\n").build();
|
||||||
.put("exe", "").build();
|
|
||||||
|
|
||||||
assertEquals(ShellToken.tokenValueMap(OsFamily.UNIX), expected);
|
assertEquals(ShellToken.tokenValueMap(OsFamily.UNIX), expected);
|
||||||
}
|
}
|
||||||
|
@ -51,9 +50,7 @@ public class ShellTokenTest {
|
||||||
Map<String, String> expected = new ImmutableMap.Builder<String, String>().put("fs", "\\")
|
Map<String, String> expected = new ImmutableMap.Builder<String, String>().put("fs", "\\")
|
||||||
.put("ps", ";").put("lf", "\r\n").put("sh", "cmd").put("source", "@call").put("rem",
|
.put("ps", ";").put("lf", "\r\n").put("sh", "cmd").put("source", "@call").put("rem",
|
||||||
"@rem").put("args", "%*").put("varstart", "%").put("varend", "%").put(
|
"@rem").put("args", "%*").put("varstart", "%").put("varend", "%").put(
|
||||||
"shebang", "@echo off\r\n").put("zeroPath",
|
"libraryPathVariable", "PATH").put("shebang", "@echo off\r\n").build();
|
||||||
"set PATH=c:\\windows\\;C:\\windows\\system32\r\n").put("exe", ".exe")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assertEquals(ShellToken.tokenValueMap(OsFamily.WINDOWS), expected);
|
assertEquals(ShellToken.tokenValueMap(OsFamily.WINDOWS), expected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,13 @@
|
||||||
package org.jclouds.initbuilder.util;
|
package org.jclouds.initbuilder.util;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import org.jclouds.initbuilder.domain.OsFamily;
|
import org.jclouds.initbuilder.domain.OsFamily;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,6 +56,26 @@ public class UtilsTest {
|
||||||
"set MAVEN_OPTS=-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError\r\n");
|
"set MAVEN_OPTS=-Xms128m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWritePositionalVarsUNIX() {
|
||||||
|
assertEquals(Utils.writePositionalVars(ImmutableList.of("host", "port"), OsFamily.UNIX),
|
||||||
|
"set HOST=$1\nshift\nset PORT=$1\nshift\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWritePositionalVarsWindows() {
|
||||||
|
assertEquals(Utils.writePositionalVars(ImmutableList.of("host", "port"), OsFamily.WINDOWS),
|
||||||
|
"set HOST=%1\r\nshift\r\nset PORT=%1\r\nshift\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteUnsetVariablesUNIX() {
|
||||||
|
assertEquals(Utils.writeUnsetVariables(ImmutableList.of("host", "port"), OsFamily.UNIX),
|
||||||
|
"unset HOST PORT\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteUnsetVariablesWindows() {
|
||||||
|
assertEquals(Utils.writeUnsetVariables(ImmutableList.of("host", "port"), OsFamily.WINDOWS),
|
||||||
|
"set HOST=\r\nset PORT=\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
public void testWriteSwitchUNIX() {
|
public void testWriteSwitchUNIX() {
|
||||||
assertEquals(Utils.writeSwitch("i", ImmutableMap.of("0", "echo hello zero", "1",
|
assertEquals(Utils.writeSwitch("i", ImmutableMap.of("0", "echo hello zero", "1",
|
||||||
"echo hello one"), OsFamily.UNIX),
|
"echo hello one"), OsFamily.UNIX),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
unset PATH JAVA_HOME LD_LIBRARY_PATH
|
||||||
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
||||||
export JAVA_HOME="/apps/jdk1.6"
|
export JAVA_HOME="/apps/jdk1.6"
|
||||||
case $1 in
|
case $1 in
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
@echo off
|
@echo off
|
||||||
|
set PATH=
|
||||||
|
set JAVA_HOME=
|
||||||
|
set PATH=
|
||||||
set PATH=c:\windows\;C:\windows\system32
|
set PATH=c:\windows\;C:\windows\system32
|
||||||
set JAVA_HOME=/apps/jdk1.6
|
set JAVA_HOME=/apps/jdk1.6
|
||||||
goto CASE%1
|
goto CASE%1
|
||||||
|
|
Loading…
Reference in New Issue