new support for InstallJDK statement and setupPublicCurl fn

This commit is contained in:
Adrian Cole 2012-02-13 21:44:27 +01:00
parent 18d79ae189
commit e277b792ab
20 changed files with 845 additions and 218 deletions

View File

@ -0,0 +1,55 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.scriptbuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.collect.ForwardingObject;
/**
* you cannot return from a top-level script, so if you are using snippets that
* issue {@code return} then you'll want to wrap them in this.
*
* @author Adrian Cole
*
*/
public class ExitInsteadOfReturn extends ForwardingObject implements Statement {
private final Statement delegate;
public ExitInsteadOfReturn(Statement delegate) {
this.delegate = delegate;
}
@Override
public Iterable<String> functionDependencies(OsFamily family) {
return delegate().functionDependencies(family);
}
@Override
public String render(OsFamily family) {
return delegate().render(family).toString().replaceAll(ShellToken.RETURN.to(family), ShellToken.EXIT.to(family));
}
@Override
protected Statement delegate() {
return delegate;
}
}

View File

@ -19,10 +19,7 @@
package org.jclouds.scriptbuilder; package org.jclouds.scriptbuilder;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.createRunScript; import static org.jclouds.scriptbuilder.domain.Statements.createRunScript;
import static org.jclouds.scriptbuilder.domain.Statements.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.forget;
import static org.jclouds.scriptbuilder.domain.Statements.interpret; import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import static org.jclouds.scriptbuilder.domain.Statements.kill; import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList; import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
@ -51,68 +48,67 @@ public class InitBuilder extends ScriptBuilder {
private final StatementList initStatement; private final StatementList initStatement;
private final CreateRunScript createRunScript; private final CreateRunScript createRunScript;
public InitBuilder(String instanceName, Statement initStatement, Statement runStatement) {
this(instanceName, ImmutableSet.of(initStatement), ImmutableSet.of(runStatement));
}
public InitBuilder(String instanceName, Iterable<Statement> initStatements, Iterable<Statement> statements) {
this(instanceName, String.format("{varl}HOME{varr}{fs}instances{fs}%s", instanceName), String.format(
"{varl}HOME{varr}{fs}instances{fs}%s", instanceName), ImmutableMap.<String, String> of(), initStatements,
statements);
}
public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables, public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables,
Iterable<Statement> statements) { Iterable<Statement> statements) {
this(instanceName, instanceHome, logDir, variables, ImmutableSet.<Statement> of(), statements); this(instanceName, instanceHome, logDir, variables, ImmutableSet.<Statement> of(), statements);
} }
public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables, public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables,
Iterable<Statement> initStatements, Iterable<Statement> statements) { Iterable<Statement> initStatements, Iterable<Statement> statements) {
Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName, "instanceHome", Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName, "instanceHome",
instanceHome, "logDir", logDir); instanceHome, "logDir", logDir);
this.initStatement = new StatementList(initStatements); this.initStatement = new StatementList(initStatements);
this.createRunScript = createRunScript(instanceName,// TODO: convert this.createRunScript = createRunScript(instanceName,// TODO: convert
// so // so
// that // that
// createRunScript // createRunScript
// can take from a // can take from a
// variable // variable
Iterables.concat(variables.keySet(), defaultVariables.keySet()), "{varl}INSTANCE_HOME{varr}", statements); Iterables.concat(variables.keySet(), defaultVariables.keySet()), "{varl}INSTANCE_HOME{varr}", statements);
this.instanceName = checkNotNull(instanceName, "instanceName"); this.instanceName = checkNotNull(instanceName, "instanceName");
this.instanceHome = checkNotNull(instanceHome, "instanceHome"); this.instanceHome = checkNotNull(instanceHome, "instanceHome");
this.logDir = checkNotNull(logDir, "logDir"); this.logDir = checkNotNull(logDir, "logDir");
addEnvironmentVariableScope("default", defaultVariables) addEnvironmentVariableScope("default", defaultVariables)
.addEnvironmentVariableScope(instanceName, variables) .addEnvironmentVariableScope(instanceName, variables)
.addStatement( .addStatement(
switchArg( switchArg(
1, 1,
new ImmutableMap.Builder<String, Statement>() new ImmutableMap.Builder<String, Statement>()
.put( .put("init",
"init", newStatementList(call("default"), call(instanceName), initStatement,
newStatementList(call("default"), call(instanceName), initStatement, createRunScript))
createRunScript)) .put("status",
.put( newStatementList(call("default"), findPid("{varl}INSTANCE_NAME{varr}"),
"status", interpret("echo [{varl}FOUND_PID{varr}]{lf}")))
newStatementList(call("default"), .put("stop",
findPid("{varl}INSTANCE_NAME{varr}"), newStatementList(call("default"), findPid("{varl}INSTANCE_NAME{varr}"), kill()))
interpret("echo [{varl}FOUND_PID{varr}]{lf}"))) .put("start",
.put( newStatementList(
"stop", call("default"),
newStatementList(call("default"), forget("{varl}INSTANCE_NAME{varr}",
findPid("{varl}INSTANCE_NAME{varr}"), kill())) "{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}",
.put( "{varl}LOG_DIR{varr}")))
"start", .put("tail",
newStatementList( newStatementList(call("default"),
call("default"), interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log{lf}")))
forget( .put("tailerr",
"{varl}INSTANCE_NAME{varr}", newStatementList(call("default"),
"{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}", interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log{lf}")))
"{varl}LOG_DIR{varr}"))) .put("run",
.put( newStatementList(call("default"),
"tail", interpret("{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}{lf}")))
newStatementList(call("default"), .build()));
interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log{lf}")))
.put(
"tailerr",
newStatementList(call("default"),
interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log{lf}")))
.put(
"run",
newStatementList(
call("default"),
interpret("{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}{lf}")))
.build()));
} }
@Override @Override

View File

@ -23,20 +23,25 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List; 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.Set;
import org.jclouds.scriptbuilder.domain.AcceptsStatementVisitor; import org.jclouds.scriptbuilder.domain.AcceptsStatementVisitor;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken; import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementVisitor; import org.jclouds.scriptbuilder.domain.StatementVisitor;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.scriptbuilder.util.Utils; import org.jclouds.scriptbuilder.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/** /**
* Creates a shell script. * Creates a shell script.
@ -75,6 +80,20 @@ public class ScriptBuilder implements Statement, AcceptsStatementVisitor {
return this; return this;
} }
// TODO: make scriptbuilder smart enough to know when a statement is a direct
// child of the script, and automatically convert
public static Statement forget(String instanceName, String script, String logDir) {
return new ExitInsteadOfReturn(Statements.forget(instanceName, script, logDir));
}
public static Statement findPid(String pid) {
return new ExitInsteadOfReturn(Statements.findPid(pid));
}
public static Statement call(String fn, String... args) {
return new ExitInsteadOfReturn(Statements.call(fn, args));
}
/** /**
* builds the shell script, by adding the following * builds the shell script, by adding the following
* <ol> * <ol>
@ -93,63 +112,66 @@ public class ScriptBuilder implements Statement, AcceptsStatementVisitor {
functions.put("abort", Utils.writeFunctionFromResource("abort", osFamily)); functions.put("abort", Utils.writeFunctionFromResource("abort", osFamily));
for (Entry<String, Map<String, String>> entry : variableScopes.entrySet()) { for (Entry<String, Map<String, String>> entry : variableScopes.entrySet()) {
functions.put(entry.getKey(), Utils.writeFunction(entry.getKey(), Utils.writeVariableExporters(entry functions.put(entry.getKey(),
.getValue()))); Utils.writeFunction(entry.getKey(), Utils.writeVariableExporters(entry.getValue())));
} }
final Map<String, String> tokenValueMap = ShellToken.tokenValueMap(osFamily); final Map<String, String> tokenValueMap = ShellToken.tokenValueMap(osFamily);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(ShellToken.BEGIN_SCRIPT.to(osFamily)); builder.append(ShellToken.BEGIN_SCRIPT.to(osFamily));
builder.append(Utils.writeUnsetVariables(Lists.newArrayList(Iterables.transform(variablesToUnset, builder.append(Utils.writeUnsetVariables(
new Function<String, String>() { Lists.newArrayList(Iterables.transform(variablesToUnset, new Function<String, String>() {
@Override @Override
public String apply(String from) { public String apply(String from) {
if (tokenValueMap.containsKey(from + "Variable")) if (tokenValueMap.containsKey(from + "Variable"))
return Utils.FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL.apply(tokenValueMap return Utils.FUNCTION_UPPER_UNDERSCORE_TO_LOWER_CAMEL.apply(tokenValueMap.get(from + "Variable"));
.get(from + "Variable")); return from;
return from; }
}
})), osFamily)); })), osFamily));
resolveFunctionDependencies(functions, osFamily); Map<String, String> functionsToWrite = resolveFunctionDependenciesForStatements(functions, statements, osFamily);
if (functions.size() > 0) { writeFunctions(functionsToWrite, osFamily, builder);
builder.append(ShellToken.BEGIN_FUNCTIONS.to(osFamily));
for (String function : functions.values()) {
builder.append(Utils.replaceTokens(function, tokenValueMap));
}
builder.append(ShellToken.END_FUNCTIONS.to(osFamily));
}
builder.append(Utils.writeZeroPath(osFamily)); builder.append(Utils.writeZeroPath(osFamily));
StringBuilder statementBuilder = new StringBuilder(); StringBuilder statementBuilder = new StringBuilder();
for (Statement statement : statements) { for (Statement statement : statements) {
statementBuilder.append(statement.render(osFamily)); statementBuilder.append(statement.render(osFamily));
} }
builder.append(statementBuilder.toString().replaceAll(ShellToken.RETURN.to(osFamily), builder.append(statementBuilder.toString());
ShellToken.EXIT.to(osFamily)));
builder.append(ShellToken.END_SCRIPT.to(osFamily)); builder.append(ShellToken.END_SCRIPT.to(osFamily));
return builder.toString(); return builder.toString();
} }
@VisibleForTesting public static void writeFunctions(Map<String, String> functionsToWrite, OsFamily osFamily, StringBuilder builder) {
void resolveFunctionDependencies(Map<String, String> functions, final OsFamily osFamily) { if (functionsToWrite.size() > 0) {
Iterable<String> dependentFunctions = Iterables.concat(Iterables.transform(statements, builder.append(ShellToken.BEGIN_FUNCTIONS.to(osFamily));
new Function<Statement, Iterable<String>>() { for (String function : functionsToWrite.values()) {
@Override builder.append(Utils.replaceTokens(function, ShellToken.tokenValueMap(osFamily)));
public Iterable<String> apply(Statement from) { }
return from.functionDependencies(osFamily); builder.append(ShellToken.END_FUNCTIONS.to(osFamily));
}
}));
List<String> unresolvedFunctions = Lists.newArrayList(dependentFunctions);
Iterables.removeAll(unresolvedFunctions, functions.keySet());
for (String functionName : unresolvedFunctions) {
functions.put(functionName, Utils.writeFunctionFromResource(functionName, osFamily));
} }
} }
@VisibleForTesting
public static Map<String, String> resolveFunctionDependenciesForStatements(Map<String, String> knownFunctions,
Iterable<Statement> statements, final OsFamily osFamily) {
Builder<String, String> builder = ImmutableMap.<String, String> builder();
builder.putAll(knownFunctions);
Set<String> dependentFunctions = ImmutableSet.copyOf(Iterables.concat(Iterables.transform(statements,
new Function<Statement, Iterable<String>>() {
@Override
public Iterable<String> apply(Statement from) {
return from.functionDependencies(osFamily);
}
})));
for (String unresolved : Sets.difference(dependentFunctions, knownFunctions.keySet()))
builder.put(unresolved, Utils.writeFunctionFromResource(unresolved, osFamily));
return builder.build();
}
@Override @Override
public Iterable<String> functionDependencies(OsFamily family) { public Iterable<String> functionDependencies(OsFamily family) {
return ImmutableSet.<String> of(); return ImmutableSet.<String> of();
} }
@Override @Override
public void accept(StatementVisitor visitor) { public void accept(StatementVisitor visitor) {
for (Statement statement : statements) { for (Statement statement : statements) {

View File

@ -19,6 +19,10 @@
package org.jclouds.scriptbuilder.domain; package org.jclouds.scriptbuilder.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.jclouds.scriptbuilder.domain.Statements.interpret; import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import java.util.Collections; import java.util.Collections;
@ -27,14 +31,14 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jclouds.scriptbuilder.ExitInsteadOfReturn;
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.util.Utils; import org.jclouds.scriptbuilder.util.Utils;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/** /**
* Creates a run script * Creates a run script
@ -64,8 +68,8 @@ public class CreateRunScript extends StatementList {
} }
public static final Map<OsFamily, String> OS_TO_TITLE_PATTERN = ImmutableMap.of(OsFamily.UNIX, public static final Map<OsFamily, String> OS_TO_TITLE_PATTERN = ImmutableMap.of(OsFamily.UNIX,
"echo \"PROMPT_COMMAND='echo -ne \\\"\\033]0;{title}\\007\\\"'\">>{file}\n", OsFamily.WINDOWS, "echo \"PROMPT_COMMAND='echo -ne \\\"\\033]0;{title}\\007\\\"'\">>{file}\n", OsFamily.WINDOWS,
"echo title {title}>>{file}\r\n"); "echo title {title}>>{file}\r\n");
@Override @Override
public Iterable<String> functionDependencies(OsFamily family) { public Iterable<String> functionDependencies(OsFamily family) {
@ -75,7 +79,7 @@ public class CreateRunScript extends StatementList {
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_TITLE_PATTERN.get(family), return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_TITLE_PATTERN.get(family),
ImmutableMap.of("title", title, "file", file))); ImmutableMap.of("title", title, "file", file)));
} }
} }
@ -91,8 +95,7 @@ public class CreateRunScript extends StatementList {
} }
public static final Map<OsFamily, String> OS_TO_EXPORT_PATTERN = ImmutableMap.of(OsFamily.UNIX, public static final Map<OsFamily, String> OS_TO_EXPORT_PATTERN = ImmutableMap.of(OsFamily.UNIX,
"echo \"export {export}='{value}'\">>{file}\n", OsFamily.WINDOWS, "echo \"export {export}='{value}'\">>{file}\n", OsFamily.WINDOWS, "echo set {export}={value}>>{file}\r\n");
"echo set {export}={value}>>{file}\r\n");
@Override @Override
public Iterable<String> functionDependencies(OsFamily family) { public Iterable<String> functionDependencies(OsFamily family) {
@ -102,12 +105,12 @@ public class CreateRunScript extends StatementList {
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_EXPORT_PATTERN.get(family), return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_EXPORT_PATTERN.get(family),
ImmutableMap.of("export", export, "value", value, "file", file))); ImmutableMap.of("export", export, "value", value, "file", file)));
} }
} }
public static String escapeVarTokens(String toEscape, OsFamily family) { public static String escapeVarTokens(String toEscape, OsFamily family) {
Map<String, String> inputToEscape = Maps.newHashMap(); Map<String, String> inputToEscape = newHashMap();
for (ShellToken token : ImmutableList.of(ShellToken.VARL, ShellToken.VARR)) { for (ShellToken token : ImmutableList.of(ShellToken.VARL, ShellToken.VARR)) {
if (!token.to(family).equals("")) { if (!token.to(family).equals("")) {
String tokenS = "{" + token.toString().toLowerCase() + "}"; String tokenS = "{" + token.toString().toLowerCase() + "}";
@ -126,11 +129,11 @@ public class CreateRunScript extends StatementList {
} }
public static final Map<OsFamily, String> OS_TO_CHMOD_PATTERN = ImmutableMap.of(OsFamily.UNIX, "chmod u+x {file}\n", public static final Map<OsFamily, String> OS_TO_CHMOD_PATTERN = ImmutableMap.of(OsFamily.UNIX, "chmod u+x {file}\n",
OsFamily.WINDOWS, ""); OsFamily.WINDOWS, "");
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
List<Statement> statements = Lists.newArrayList(); List<Statement> statements = newArrayList();
Map<String, String> tokenMap = ShellToken.tokenValueMap(family); Map<String, String> tokenMap = ShellToken.tokenValueMap(family);
String runScript = Utils.replaceTokens(pwd + "{fs}" + instanceName + ".{sh}", tokenMap); String runScript = Utils.replaceTokens(pwd + "{fs}" + instanceName + ".{sh}", tokenMap);
statements.add(interpret(String.format("{md} %s{lf}", pwd))); statements.add(interpret(String.format("{md} %s{lf}", pwd)));
@ -152,13 +155,12 @@ public class CreateRunScript extends StatementList {
} }
statements.add(new AddTitleToFile(instanceName, runScript)); statements.add(new AddTitleToFile(instanceName, runScript));
statements.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family), ""), runScript, statements.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family), ""), runScript,
family)); family));
statements.add(new AddExportToFile("instanceName", instanceName, runScript)); statements.add(new AddExportToFile("instanceName", instanceName, runScript));
for (String export : exports) { for (String export : exports) {
statements statements.add(new AddExportToFile(export, Utils.replaceTokens(
.add(new AddExportToFile(export, Utils.replaceTokens("{varl}" "{varl}" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}", tokenMap),
+ CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}", tokenMap), runScript));
runScript));
} }
statements.add(appendToFile("{cd} " + pwd, runScript, family)); statements.add(appendToFile("{cd} " + pwd, runScript, family));
statements.addAll(statements); statements.addAll(statements);
@ -168,7 +170,7 @@ public class CreateRunScript extends StatementList {
} }
} }
statements statements
.add(interpret(Utils.replaceTokens(OS_TO_CHMOD_PATTERN.get(family), ImmutableMap.of("file", runScript)))); .add(interpret(Utils.replaceTokens(OS_TO_CHMOD_PATTERN.get(family), ImmutableMap.of("file", runScript))));
return new StatementList(statements).render(family); return new StatementList(statements).render(family);
} }
@ -184,6 +186,11 @@ public class CreateRunScript extends StatementList {
builder.append("cat >> ").append(runScript).append(" <<'").append(MARKER).append("'\n"); builder.append("cat >> ").append(runScript).append(" <<'").append(MARKER).append("'\n");
builder.append("cd ").append(pwd).append("\n"); builder.append("cd ").append(pwd).append("\n");
for (Statement statement : statements) { for (Statement statement : statements) {
if (statement instanceof Call
|| (statement instanceof StatementList && any(StatementList.class.cast(statement).delegate(),
instanceOf(Call.class)))) {
statement = new ExitInsteadOfReturn(statement);
}
builder.append(statement.render(OsFamily.UNIX)).append("\n"); builder.append(statement.render(OsFamily.UNIX)).append("\n");
} }
builder.append(MARKER).append("\n"); builder.append(MARKER).append("\n");
@ -200,6 +207,16 @@ public class CreateRunScript extends StatementList {
String variableNameInUpper = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export); String variableNameInUpper = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export);
builder.append("export ").append(variableNameInUpper).append("='$").append(variableNameInUpper).append("'\n"); builder.append("export ").append(variableNameInUpper).append("='$").append(variableNameInUpper).append("'\n");
} }
Map<String, String> functionsToWrite = ScriptBuilder.resolveFunctionDependenciesForStatements(
ImmutableMap.<String, String> of("abort", Utils.writeFunctionFromResource("abort", family)), statements,
family);
// if there are more functions than simply abort
if (functionsToWrite.size() > 1) {
StringBuilder inNeedOfEscaping = new StringBuilder();
ScriptBuilder.writeFunctions(functionsToWrite, family, inNeedOfEscaping);
builder.append(inNeedOfEscaping.toString().replace("$", "\\$"));
}
builder.append(MARKER).append("\n"); builder.append(MARKER).append("\n");
} }
@ -211,7 +228,7 @@ public class CreateRunScript extends StatementList {
line = escapeVarTokens(line, family); line = escapeVarTokens(line, family);
} }
return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line, return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
quote, runScript))); quote, runScript)));
} }
public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*"); public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");

View File

@ -46,17 +46,22 @@ public class SaveHttpResponseTo extends InterpretableStatement {
* request headers to send * request headers to send
*/ */
public SaveHttpResponseTo(String dir, String file, String method, URI endpoint, Multimap<String, String> headers) { public SaveHttpResponseTo(String dir, String file, String method, URI endpoint, Multimap<String, String> headers) {
super(String.format("({md} %s && {cd} %s && [ ! -f %s ] && %s -C - -X %s %s %s >%s)\n", dir, dir, file, CURL, super(String.format(
method, Joiner.on(' ').join( "({md} %s && {cd} %s && [ ! -f %s ] && %s -C - -X %s %s %s >%s)\n",
Iterables.transform(headers.entries(), new Function<Map.Entry<String, String>, String>() { dir,
dir,
file,
CURL,
method,
Joiner.on(' ').join(
Iterables.transform(headers.entries(), new Function<Map.Entry<String, String>, String>() {
@Override @Override
public String apply(Map.Entry<String, String> from) { public String apply(Map.Entry<String, String> from) {
return String.format("-H \"%s: %s\"", from.getKey(), from.getValue()); return String.format("-H \"%s: %s\"", from.getKey(), from.getValue());
} }
})), endpoint.toASCIIString(), file)); })), endpoint.toASCIIString(), file));
} }
} }

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List; import java.util.List;
import com.google.common.collect.ForwardingList;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableList.Builder;
@ -30,7 +31,7 @@ import com.google.common.collect.ImmutableList.Builder;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class StatementList implements Statement, AcceptsStatementVisitor { public class StatementList extends ForwardingList<Statement> implements Statement, AcceptsStatementVisitor {
public final List<Statement> statements; public final List<Statement> statements;
@ -44,7 +45,7 @@ public class StatementList implements Statement, AcceptsStatementVisitor {
public String render(OsFamily family) { public String render(OsFamily family) {
StringBuilder statementsBuilder = new StringBuilder(); StringBuilder statementsBuilder = new StringBuilder();
for (Statement statement : statements) { for (Statement statement : delegate()) {
statementsBuilder.append(statement.render(family)); statementsBuilder.append(statement.render(family));
} }
return statementsBuilder.toString(); return statementsBuilder.toString();
@ -53,41 +54,21 @@ public class StatementList implements Statement, AcceptsStatementVisitor {
@Override @Override
public Iterable<String> functionDependencies(OsFamily family) { public Iterable<String> functionDependencies(OsFamily family) {
Builder<String> functions = ImmutableList.<String> builder(); Builder<String> functions = ImmutableList.<String> builder();
for (Statement statement : statements) { for (Statement statement : delegate()) {
functions.addAll(statement.functionDependencies(family)); functions.addAll(statement.functionDependencies(family));
} }
return functions.build(); return functions.build();
} }
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((statements == null) ? 0 : statements.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StatementList other = (StatementList) obj;
if (statements == null) {
if (other.statements != null)
return false;
} else if (!statements.equals(other.statements))
return false;
return true;
}
@Override @Override
public void accept(StatementVisitor visitor) { public void accept(StatementVisitor visitor) {
for (Statement statement : statements) { for (Statement statement : delegate()) {
visitor.visit(statement); visitor.visit(statement);
} }
} }
@Override
public List<Statement> delegate() {
return statements;
}
} }

View File

@ -22,6 +22,7 @@ import java.net.URI;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
@ -157,7 +158,11 @@ public class Statements {
String directory) { String directory) {
return new PipeHttpResponseToTarxpzfIntoDirectory(method, endpoint, headers, directory); return new PipeHttpResponseToTarxpzfIntoDirectory(method, endpoint, headers, directory);
} }
public static Statement extractTargzIntoDirectory(URI targz, String directory) {
return extractTargzIntoDirectory("GET", targz, ImmutableMultimap.<String, String>of(), directory);
}
/** /**
* unzip the data received from the request parameters. * unzip the data received from the request parameters.
* *
@ -174,6 +179,10 @@ public class Statements {
return new UnzipHttpResponseIntoDirectory(method, endpoint, headers, directory); return new UnzipHttpResponseIntoDirectory(method, endpoint, headers, directory);
} }
public static Statement saveHttpResponseTo(URI source, String dir, String file) {
return new SaveHttpResponseTo(dir, file, "GET", source, ImmutableMultimap.<String, String> of());
}
/** /**
* exec the data received from the request parameters. * exec the data received from the request parameters.
* *

View File

@ -0,0 +1,76 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.scriptbuilder.statements.java;
import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.jclouds.scriptbuilder.domain.Statements.extractTargzIntoDirectory;
import java.net.URI;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import com.google.common.collect.ImmutableSet;
/**
* Installs a default JDK to a host
*
* @author Adrian Cole
*/
public class InstallJDK {
public static Statement fromURL() {
return new FromURL();
}
public static Statement fromURL(URI url) {
return new FromURL(url);
}
static class FromURL extends StatementList {
public static final URI JDK7_URL = URI.create(System.getProperty("jdk7-url",
"http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-x64.tar.gz"));
public FromURL() {
this(JDK7_URL);
}
public static final ImmutableSet<String> exportJavaHomeAndAddToPath = ImmutableSet.of(
"export JAVA_HOME=/usr/local/jdk", "export PATH=$JAVA_HOME/bin:$PATH");
public FromURL(URI jdk7Url) {
super(call("setupPublicCurl"), //
extractTargzIntoDirectory(jdk7Url, "/usr/local"),//
exec("mv /usr/local/jdk* /usr/local/jdk/"),//
exec("test -n \"$SUDO_USER\" && "), //
appendFile("/home/$SUDO_USER/.bashrc", exportJavaHomeAndAddToPath),//
appendFile("/etc/bashrc", exportJavaHomeAndAddToPath),//
appendFile("$HOME/.bashrc", exportJavaHomeAndAddToPath),//
appendFile("/etc/skel/.bashrc", exportJavaHomeAndAddToPath),//
// TODO:
// eventhough we are setting the above, sometimes images (ex.
// cloudservers ubuntu) kick out of .bashrc (ex. [ -z "$PS1" ] &&
// return), for this reason, we should also explicitly link.
// A better way would be to update using alternatives or the like
exec("ln -fs /usr/local/jdk/bin/java /usr/bin/java"));
}
}
}

View File

@ -0,0 +1,50 @@
alias apt-get-install="apt-get install -f -y -qq --force-yes"
alias apt-get-upgrade="(apt-get update -qq&&apt-get upgrade -y -qq)"
function ensure_cmd_or_install_package_apt(){
local cmd=$1
local pkg=$2
hash $cmd 2>/dev/null || apt-get-install $pkg || ( apt-get-upgrade && apt-get-install $pkg )
}
function ensure_cmd_or_install_package_yum(){
local cmd=$1
local pkg=$2
hash $cmd 2>/dev/null || yum --nogpgcheck -y ensure $pkg
}
function ensure_netutils_apt() {
ensure_cmd_or_install_package_apt nslookup dnsutils
ensure_cmd_or_install_package_apt curl curl
}
function ensure_netutils_yum() {
ensure_cmd_or_install_package_yum nslookup bind-utils
ensure_cmd_or_install_package_yum curl curl
}
# most network services require that the hostname is in
# the /etc/hosts file, or they won't operate
function ensure_hostname_in_hosts() {
egrep -q `hostname` /etc/hosts || awk -v hostname=`hostname` 'END { print $1" "hostname }' /proc/net/arp >> /etc/hosts
}
# download locations for many services are at public dns
function ensure_can_resolve_public_dns() {
nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
}
function setupPublicCurl() {
ensure_hostname_in_hosts
if hash apt-get 2>/dev/null; then
ensure_netutils_apt
elif hash yum 2>/dev/null; then
ensure_netutils_yum
else
abort "we only support apt-get and yum right now... please contribute!"
return 1
fi
ensure_can_resolve_public_dns
return 0
}

View File

@ -18,8 +18,8 @@
*/ */
package org.jclouds.scriptbuilder; package org.jclouds.scriptbuilder;
import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.appendFile; import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
@ -45,48 +45,57 @@ import com.google.common.io.Resources;
public class InitBuilderTest { public class InitBuilderTest {
InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap.of("tmpDir", InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap.of("tmpDir",
"/mnt/tmp"), ImmutableList.<Statement> of( "/mnt/tmp"), ImmutableList.<Statement> of(
appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList.<String> of("hello world")), call("find /"))); appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList.<String> of("hello world")),
exec("find /")));
@Test @Test
public void testBuildSimpleWindows() throws MalformedURLException, IOException { public void testBuildSimpleWindows() throws MalformedURLException, IOException {
assertEquals(testInitBuilder.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(
.getResource("test_init." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8))); testInitBuilder.render(OsFamily.WINDOWS),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_init." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testBuildSimpleUNIX() throws MalformedURLException, IOException { public void testBuildSimpleUNIX() throws MalformedURLException, IOException {
assertEquals(testInitBuilder.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(
.getResource("test_init." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); testInitBuilder.render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_init." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
@Test @Test
public void testBuildEBS() throws MalformedURLException, IOException { public void testBuildEBS() throws MalformedURLException, IOException {
assertEquals( assertEquals(
new InitBuilder( new InitBuilder("mkebsboot",// name of the script
"mkebsboot",// name of the script "/tmp",// working directory
"/tmp",// working directory "/tmp/logs",// location of stdout.log and stderr.log
"/tmp/logs",// location of stdout.log and stderr.log ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables // used
// used // inside
// inside // of
// of // the
// the // script
// script ImmutableList.<Statement> of(Statements
ImmutableList.<Statement> of(Statements.interpret("echo creating a filesystem and mounting the ebs volume",// what to execute .interpret(
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}", "echo creating a filesystem and mounting the ebs volume",// what
"rm -rf {varl}IMAGE_DIR{varr}/*", // to
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-", // execute
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}", "{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
"echo making a local working copy of the boot disk", "rm -rf {varl}IMAGE_DIR{varr}/*",
"rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}", "yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
"echo preparing the local working copy", "mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data", "echo making a local working copy of the boot disk",
"echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}", "rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs", "echo preparing the local working copy",
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
"rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo ----COMPLETE----") "echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}",
)).render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources "tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
.getResource("test_ebs." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); "du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source",
"du -sk {varl}IMAGE_DIR{varr}", "rm -rf {varl}IMAGE_DIR{varr}/*",
"umount {varl}EBS_MOUNT_POINT{varr}", "echo ----COMPLETE----"))).render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_ebs." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
} }

View File

@ -18,9 +18,9 @@
*/ */
package org.jclouds.scriptbuilder; package org.jclouds.scriptbuilder;
import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.ScriptBuilder.call;
import static org.jclouds.scriptbuilder.ScriptBuilder.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.appendFile; import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
import static org.jclouds.scriptbuilder.domain.Statements.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.interpret; import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import static org.jclouds.scriptbuilder.domain.Statements.kill; import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList; import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
@ -49,50 +49,53 @@ import com.google.common.io.Resources;
public class ScriptBuilderTest { public class ScriptBuilderTest {
ScriptBuilder testScriptBuilder = new ScriptBuilder() ScriptBuilder testScriptBuilder = new ScriptBuilder()
.unsetEnvironmentVariable("runtime") .unsetEnvironmentVariable("runtime")
.addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo")) .addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo"))
.addStatement( .addStatement(
switchArg( switchArg(1, ImmutableMap.of(
1, "start",
ImmutableMap newStatementList(call("default"), interpret("echo start {varl}RUNTIME{varr}{lf}")),
.of( "stop",
"start", newStatementList(call("default"), interpret("echo stop {varl}RUNTIME{varr}{lf}")),
newStatementList(call("default"), "status",
interpret("echo start {varl}RUNTIME{varr}{lf}")), newStatementList(
"stop", appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt",
newStatementList(call("default"), ImmutableList.<String> of("hello world")),
interpret("echo stop {varl}RUNTIME{varr}{lf}")), interpret("echo {vq}the following should be []: [{varl}RUNTIME{varr}]{vq}{lf}")))));
"status",
newStatementList(
appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt",
ImmutableList.<String> of("hello world")),
interpret("echo {vq}the following should be []: [{varl}RUNTIME{varr}]{vq}{lf}")))));
@Test @Test
public void testBuildSimpleWindows() throws MalformedURLException, IOException { public void testBuildSimpleWindows() throws MalformedURLException, IOException {
assertEquals(testScriptBuilder.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier( assertEquals(
Resources.getResource("test_script." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8))); testScriptBuilder.render(OsFamily.WINDOWS),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_script." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testBuildSimpleUNIX() throws MalformedURLException, IOException { public void testBuildSimpleUNIX() throws MalformedURLException, IOException {
assertEquals(testScriptBuilder.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(
.getResource("test_script." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); testScriptBuilder.render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_script." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
ScriptBuilder findPidBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement( ScriptBuilder findPidBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement(
interpret("echo {varl}FOUND_PID{varr}{lf}")); interpret("echo {varl}FOUND_PID{varr}{lf}"));
@Test @Test
public void testFindPidWindows() throws MalformedURLException, IOException { public void testFindPidWindows() throws MalformedURLException, IOException {
assertEquals(findPidBuilder.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(
.getResource("test_find_pid." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8))); findPidBuilder.render(OsFamily.WINDOWS),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_find_pid." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testFindPidUNIX() throws MalformedURLException, IOException { public void testFindPidUNIX() throws MalformedURLException, IOException {
assertEquals(findPidBuilder.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(
.getResource("test_find_pid." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); findPidBuilder.render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_find_pid." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
ScriptBuilder seekAndDestroyBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement(kill()); ScriptBuilder seekAndDestroyBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement(kill());
@ -100,22 +103,24 @@ public class ScriptBuilderTest {
@Test @Test
public void testSeekAndDestroyWindows() throws MalformedURLException, IOException { public void testSeekAndDestroyWindows() throws MalformedURLException, IOException {
assertEquals(seekAndDestroyBuilder.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier( assertEquals(seekAndDestroyBuilder.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8))); Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testSeekAndDestroyUNIX() throws MalformedURLException, IOException { public void testSeekAndDestroyUNIX() throws MalformedURLException, IOException {
assertEquals(seekAndDestroyBuilder.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier( assertEquals(
Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); seekAndDestroyBuilder.render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
@Test @Test
public void testSwitchOn() { public void testSwitchOn() {
ScriptBuilder builder = new ScriptBuilder(); ScriptBuilder builder = new ScriptBuilder();
builder.addStatement(switchArg(1, ImmutableMap.of("start", interpret("echo started{lf}"), "stop", builder.addStatement(switchArg(1,
interpret("echo stopped{lf}")))); ImmutableMap.of("start", interpret("echo started{lf}"), "stop", interpret("echo stopped{lf}"))));
assertEquals(builder.statements, ImmutableList.of(new SwitchArg(1, ImmutableMap.of("start", assertEquals(builder.statements, ImmutableList.of(new SwitchArg(1, ImmutableMap.of("start",
interpret("echo started{lf}"), "stop", interpret("echo stopped{lf}"))))); interpret("echo started{lf}"), "stop", interpret("echo stopped{lf}")))));
} }
@Test @Test

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.scriptbuilder.domain; package org.jclouds.scriptbuilder.domain;
import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.jclouds.scriptbuilder.domain.Statements.appendFile; import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
import static org.jclouds.scriptbuilder.domain.Statements.createRunScript; import static org.jclouds.scriptbuilder.domain.Statements.createRunScript;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -43,10 +43,10 @@ public class CreateRunScriptTest {
"{tmp}{fs}{uid}{fs}scripttest", "{tmp}{fs}{uid}{fs}scripttest",
ImmutableList ImmutableList
.<Statement> of( .<Statement> of(
call("echo hello"), exec("echo hello"),
appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList appendFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList
.<String> of("hello world")), .<String> of("hello world")),
call("echo {varl}JAVA_HOME{varr}{fs}bin{fs}java -DinstanceName={varl}INSTANCE_NAME{varr} myServer.Main"))); exec("echo {varl}JAVA_HOME{varr}{fs}bin{fs}java -DinstanceName={varl}INSTANCE_NAME{varr} myServer.Main")));
public void testUNIX() throws IOException { public void testUNIX() throws IOException {
assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources

View File

@ -0,0 +1,45 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.scriptbuilder.domain;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SaveHttpResponseToTest")
public class SaveHttpResponseToTest {
public void testSaveHttpResponseToDirAndFileUNIX() {
SaveHttpResponseTo testWithDir = new SaveHttpResponseTo("/tmp", "install", "GET",
URI.create("https://adriancolehappy.s3.amazonaws.com/java/install"), ImmutableMultimap.of("Host",
"adriancolehappy.s3.amazonaws.com", "Date", "Sun, 12 Sep 2010 08:25:19 GMT", "Authorization",
"AWS 0ASHDJAS82:JASHFDA="));
assertEquals(
testWithDir.render(OsFamily.UNIX),
"(mkdir -p /tmp && cd /tmp && [ ! -f install ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET -H \"Host: adriancolehappy.s3.amazonaws.com\" -H \"Date: Sun, 12 Sep 2010 08:25:19 GMT\" -H \"Authorization: AWS 0ASHDJAS82:JASHFDA=\" https://adriancolehappy.s3.amazonaws.com/java/install >install)\n");
}
}

View File

@ -0,0 +1,52 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.scriptbuilder.domain;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "StatementsTest")
public class StatementsTest {
public void testSaveHttpResponseToUNIX() {
Statement save = Statements.saveHttpResponseTo(
URI.create("https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.jar"), "/opt/minecraft",
"minecraft_server.jar");
assertEquals(
save.render(OsFamily.UNIX),
"(mkdir -p /opt/minecraft && cd /opt/minecraft && [ ! -f minecraft_server.jar ] && curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -C - -X GET https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.jar >minecraft_server.jar)\n");
}
public void testExtractTargzIntoDirectoryUNIX() {
Statement save = Statements
.extractTargzIntoDirectory(
URI.create("https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.tar.gz"),
"/opt/minecraft");
assertEquals(
save.render(OsFamily.UNIX),
"curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.tar.gz |(mkdir -p /opt/minecraft &&cd /opt/minecraft &&tar -xpzf -)\n");
}
}

View File

@ -0,0 +1,67 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.scriptbuilder.statements.java;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.scriptbuilder.domain.Statement;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "InstallJDKTest")
public class InstallJDKTest {
Statement installJDK = InstallJDK.fromURL();
public void testInstallJDKUNIX() throws IOException {
assertEquals(InstallJDK.fromURL().render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_install_jdk_from_url." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
}
public void testInstallJDKUNIXInScriptBuilderSourcesSetupPublicCurl() throws IOException {
assertEquals(
new InitBuilder("install_jdk", ImmutableSet.<Statement> of(), ImmutableSet.<Statement> of(InstallJDK
.fromURL())).render(OsFamily.UNIX),
CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_install_jdk_scriptbuilder." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
}
public void testInstallJDKUNIXWithURL() throws IOException {
assertEquals(
InstallJDK.fromURL(URI.create("http://foo")).render(OsFamily.UNIX),
CharStreams.toString(
Resources.newReaderSupplier(
Resources.getResource("test_install_jdk_from_url." + ShellToken.SH.to(OsFamily.UNIX)),
Charsets.UTF_8)).replace(InstallJDK.FromURL.JDK7_URL.toASCIIString(), "http://foo"));
}
}

View File

@ -0,0 +1,21 @@
setupPublicCurl || return 1
curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-x64.tar.gz |(mkdir -p /usr/local &&cd /usr/local &&tar -xpzf -)
mv /usr/local/jdk* /usr/local/jdk/
test -n "$SUDO_USER" &&
cat >> /home/$SUDO_USER/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> $HOME/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/skel/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
ln -fs /usr/local/jdk/bin/java /usr/bin/java

View File

@ -84,7 +84,7 @@ cat >> /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'
hello world hello world
END_OF_FILE END_OF_FILE
find / || exit 1 find /
END_OF_SCRIPT END_OF_SCRIPT

View File

@ -0,0 +1,21 @@
setupPublicCurl || return 1
curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-x64.tar.gz |(mkdir -p /usr/local &&cd /usr/local &&tar -xpzf -)
mv /usr/local/jdk* /usr/local/jdk/
test -n "$SUDO_USER" &&
cat >> /home/$SUDO_USER/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> $HOME/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/skel/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
ln -fs /usr/local/jdk/bin/java /usr/bin/java

View File

@ -0,0 +1,196 @@
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
unset PATH JAVA_HOME LD_LIBRARY_PATH
function abort {
echo "aborting: $@" 1>&2
exit 1
}
function default {
export INSTANCE_NAME="install_jdk"
export INSTANCE_HOME="$HOME/instances/install_jdk"
export LOG_DIR="$HOME/instances/install_jdk"
return 0
}
function install_jdk {
return 0
}
function findPid {
unset FOUND_PID;
[ $# -eq 1 ] || {
abort "findPid requires a parameter of pattern to match"
return 1
}
local PATTERN="$1"; shift
local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|grep -v $$|awk '{print $2}'`
[ -n "$_FOUND" ] && {
export FOUND_PID=$_FOUND
return 0
} || {
return 1
}
}
function forget {
unset FOUND_PID;
[ $# -eq 3 ] || {
abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
return 1
}
local INSTANCE_NAME="$1"; shift
local SCRIPT="$1"; shift
local LOG_DIR="$1"; shift
mkdir -p $LOG_DIR
findPid $INSTANCE_NAME
[ -n "$FOUND_PID" -a -f $LOG_DIR/stdout.log ] && {
echo $INSTANCE_NAME already running pid [$FOUND_PID]
return 1;
} || {
nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
RETURN=$?
# this is generally followed by findPid, so we shouldn't exit
# immediately as the proc may not have registered in ps, yet
test $RETURN && sleep 1
return $RETURN;
}
}
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
case $1 in
init)
default || exit 1
install_jdk || exit 1
mkdir -p $INSTANCE_HOME
# create runscript header
cat > $INSTANCE_HOME/install_jdk.sh <<END_OF_SCRIPT
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
PROMPT_COMMAND='echo -ne "\033]0;install_jdk\007"'
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
export INSTANCE_NAME='install_jdk'
export INSTANCE_NAME='$INSTANCE_NAME'
export INSTANCE_HOME='$INSTANCE_HOME'
export LOG_DIR='$LOG_DIR'
function abort {
echo "aborting: \$@" 1>&2
exit 1
}
alias apt-get-install="apt-get install -f -y -qq --force-yes"
alias apt-get-upgrade="(apt-get update -qq&&apt-get upgrade -y -qq)"
function ensure_cmd_or_install_package_apt(){
local cmd=\$1
local pkg=\$2
hash \$cmd 2>/dev/null || apt-get-install \$pkg || ( apt-get-upgrade && apt-get-install \$pkg )
}
function ensure_cmd_or_install_package_yum(){
local cmd=\$1
local pkg=\$2
hash \$cmd 2>/dev/null || yum --nogpgcheck -y ensure \$pkg
}
function ensure_netutils_apt() {
ensure_cmd_or_install_package_apt nslookup dnsutils
ensure_cmd_or_install_package_apt curl curl
}
function ensure_netutils_yum() {
ensure_cmd_or_install_package_yum nslookup bind-utils
ensure_cmd_or_install_package_yum curl curl
}
# most network services require that the hostname is in
# the /etc/hosts file, or they won't operate
function ensure_hostname_in_hosts() {
egrep -q `hostname` /etc/hosts || awk -v hostname=`hostname` 'END { print \$1" "hostname }' /proc/net/arp >> /etc/hosts
}
# download locations for many services are at public dns
function ensure_can_resolve_public_dns() {
nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
}
function setupPublicCurl() {
ensure_hostname_in_hosts
if hash apt-get 2>/dev/null; then
ensure_netutils_apt
elif hash yum 2>/dev/null; then
ensure_netutils_yum
else
abort "we only support apt-get and yum right now... please contribute!"
return 1
fi
ensure_can_resolve_public_dns
return 0
}
END_OF_SCRIPT
# add desired commands from the user
cat >> $INSTANCE_HOME/install_jdk.sh <<'END_OF_SCRIPT'
cd $INSTANCE_HOME
setupPublicCurl || exit 1
curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-x64.tar.gz |(mkdir -p /usr/local &&cd /usr/local &&tar -xpzf -)
mv /usr/local/jdk* /usr/local/jdk/
test -n "$SUDO_USER" &&
cat >> /home/$SUDO_USER/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> $HOME/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
cat >> /etc/skel/.bashrc <<'END_OF_FILE'
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$PATH
END_OF_FILE
ln -fs /usr/local/jdk/bin/java /usr/bin/java
END_OF_SCRIPT
# add runscript footer
cat >> $INSTANCE_HOME/install_jdk.sh <<'END_OF_SCRIPT'
exit 0
END_OF_SCRIPT
chmod u+x $INSTANCE_HOME/install_jdk.sh
;;
status)
default || exit 1
findPid $INSTANCE_NAME || exit 1
echo [$FOUND_PID]
;;
stop)
default || exit 1
findPid $INSTANCE_NAME || exit 1
[ -n "$FOUND_PID" ] && {
echo stopping $FOUND_PID
kill -9 $FOUND_PID
}
;;
start)
default || exit 1
forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
;;
tail)
default || exit 1
tail $LOG_DIR/stdout.log
;;
tailerr)
default || exit 1
tail $LOG_DIR/stderr.log
;;
run)
default || exit 1
$INSTANCE_HOME/$INSTANCE_NAME.sh
;;
esac
exit 0

View File

@ -15,13 +15,13 @@ END_OF_SCRIPT
# add desired commands from the user # add desired commands from the user
cat >> /tmp/$USER/scripttest/yahooprod.sh <<'END_OF_SCRIPT' cat >> /tmp/$USER/scripttest/yahooprod.sh <<'END_OF_SCRIPT'
cd /tmp/$USER/scripttest cd /tmp/$USER/scripttest
echo hello || return 1 echo hello
cat >> /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE' cat >> /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'
hello world hello world
END_OF_FILE END_OF_FILE
echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main || return 1 echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main
END_OF_SCRIPT END_OF_SCRIPT