added create file support to scriptbuilder

This commit is contained in:
Adrian Cole 2010-09-02 01:34:40 -07:00
parent fa8386b357
commit a96471c9a8
23 changed files with 446 additions and 239 deletions

View File

@ -66,6 +66,8 @@ import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshException;
@ -75,6 +77,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -250,25 +253,25 @@ public class EBSBootEC2ClientLiveTest {
"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"),
// used ImmutableList
// inside .<Statement> of(Statements
// of .interpret(
// the "echo creating a filesystem and mounting the ebs volume",
// script
"echo creating a filesystem and mounting the ebs volume",// what to
// execute
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}", "{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
"rm -rf {varl}IMAGE_DIR{varr}/*", "rm -rf {varl}IMAGE_DIR{varr}/*",
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-", "yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}", "mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
"echo making a local working copy of the boot disk", "echo making a local working copy of the boot disk",
"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}", "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}",
"echo preparing the local working copy", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data", "echo preparing the local working copy",
"echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
"echo copying the local working copy to the ebs mount",
"{cd} {varl}IMAGE_DIR{varr}",
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs", "tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}", "du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source",
"rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END) "du -sk {varl}IMAGE_DIR{varr}", "rm -rf {varl}IMAGE_DIR{varr}/*",
"umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END)))
.build(OsFamily.UNIX); .build(OsFamily.UNIX);
} }

View File

@ -35,12 +35,15 @@ import org.jclouds.io.Payloads;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
@ -73,7 +76,7 @@ public class RunScriptOnNode implements SshCallable<ExecResponse> {
public static Payload createRunScript(String scriptName, Payload script) { public static Payload createRunScript(String scriptName, Payload script) {
String path = "/tmp/" + scriptName; String path = "/tmp/" + scriptName;
InitBuilder initBuilder = new InitBuilder(scriptName, path, path, Collections.<String, String> emptyMap(), InitBuilder initBuilder = new InitBuilder(scriptName, path, path, Collections.<String, String> emptyMap(),
splitOnNewlines(script)); ImmutableList.<Statement> of(Statements.interpret(splitOnNewlines(script))));
return Payloads.newByteArrayPayload(initBuilder.build(OsFamily.UNIX).getBytes()); return Payloads.newByteArrayPayload(initBuilder.build(OsFamily.UNIX).getBytes());
} }

View File

@ -46,6 +46,8 @@ import org.jclouds.net.IPSocket;
import org.jclouds.predicates.SocketOpen; import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshException;
@ -55,6 +57,7 @@ import org.testng.annotations.Test;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
@ -242,8 +245,8 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
public static String initScript(String scriptName, String script) { public static String initScript(String scriptName, String script) {
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName, return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName,
ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split( ImmutableMap.<String, String> of(), ImmutableList.<Statement> of(Statements.interpret(Iterables.toArray(
new String(checkNotNull(script, "script"))), String.class)) Splitter.on("\n").split(new String(checkNotNull(script, "script"))), String.class))))
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX); .build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
} }

View File

@ -30,6 +30,8 @@ import static org.jclouds.scriptbuilder.domain.Statements.switchArg;
import java.util.Map; import java.util.Map;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -41,10 +43,10 @@ import com.google.common.collect.Iterables;
public class InitBuilder extends ScriptBuilder { public class InitBuilder extends ScriptBuilder {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public InitBuilder(String instanceName, String instanceHome, String logDir, public InitBuilder(String instanceName, String instanceHome, String logDir, Map<String, String> variables,
Map<String, String> variables, String... execLines) { Iterable<Statement> statements) {
Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName, Map<String, String> defaultVariables = ImmutableMap.of("instanceName", instanceName, "instanceHome",
"instanceHome", instanceHome, "logDir", logDir); instanceHome, "logDir", logDir);
addEnvironmentVariableScope("default", defaultVariables) addEnvironmentVariableScope("default", defaultVariables)
.addEnvironmentVariableScope(instanceName, variables) .addEnvironmentVariableScope(instanceName, variables)
.addStatement( .addStatement(
@ -53,31 +55,26 @@ public class InitBuilder extends ScriptBuilder {
new ImmutableMap.Builder() new ImmutableMap.Builder()
.put( .put(
"init", "init",
newStatementList(call("default"), newStatementList(call("default"), call(instanceName),
call(instanceName), createRunScript( createRunScript(
instanceName,// TODO: convert instanceName,// TODO: convert
// so // so
// that // that
// createRunScript // createRunScript
// can take from a // can take from a
// variable // variable
Iterables.concat(variables Iterables.concat(variables.keySet(),
.keySet(), defaultVariables.keySet()),
defaultVariables "{varl}INSTANCE_HOME{varr}", statements)))
.keySet()),
"{varl}INSTANCE_HOME{varr}",
execLines)))
.put( .put(
"status", "status",
newStatementList( newStatementList(call("default"),
call("default"),
findPid("{varl}INSTANCE_NAME{varr}"), findPid("{varl}INSTANCE_NAME{varr}"),
interpret("echo [{varl}FOUND_PID{varr}]{lf}"))) interpret("echo [{varl}FOUND_PID{varr}]{lf}")))
.put( .put(
"stop", "stop",
newStatementList(call("default"), newStatementList(call("default"),
findPid("{varl}INSTANCE_NAME{varr}"), findPid("{varl}INSTANCE_NAME{varr}"), kill()))
kill()))
.put( .put(
"start", "start",
newStatementList( newStatementList(
@ -88,13 +85,11 @@ public class InitBuilder extends ScriptBuilder {
"{varl}LOG_DIR{varr}"))) "{varl}LOG_DIR{varr}")))
.put( .put(
"tail", "tail",
newStatementList( newStatementList(call("default"),
call("default"),
interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log{lf}"))) interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log{lf}")))
.put( .put(
"tailerr", "tailerr",
newStatementList( newStatementList(call("default"),
call("default"),
interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log{lf}"))) interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log{lf}")))
.put( .put(
"run", "run",

View File

@ -0,0 +1,113 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/**
* Creates a run script
*
* @author Adrian Cole
*/
public class CreateFile implements Statement {
public final static String MARKER = "END_OF_FILE";
final String path;
final Iterable<String> lines;
public CreateFile(String path, Iterable<String> lines) {// TODO: convert so
this.path = checkNotNull(path, "path");
this.lines = checkNotNull(lines, "lines");
checkState(Iterables.size(lines) > 0, "you must pass something to execute");
}
public static String escapeVarTokens(String toEscape, OsFamily family) {
Map<String, String> inputToEscape = Maps.newHashMap();
for (ShellToken token : ImmutableList.of(ShellToken.VARL, ShellToken.VARR)) {
if (!token.to(family).equals("")) {
String tokenS = "{" + token.toString().toLowerCase() + "}";
inputToEscape.put(tokenS, "{escvar}" + tokenS);
}
}
for (Entry<String, String> entry : inputToEscape.entrySet()) {
toEscape = toEscape.replace(entry.getKey(), entry.getValue());
}
return toEscape;
}
@Override
public Iterable<String> functionDependecies(OsFamily family) {
return Collections.emptyList();
}
@Override
public String render(OsFamily family) {
List<Statement> statements = Lists.newArrayList();
if (family == OsFamily.UNIX) {
StringBuilder builder = new StringBuilder();
hereFile(path, builder);
statements.add(interpret(builder.toString()));
} else {
statements.add(interpret(String.format("{rm} %s 2{closeFd}{lf}", path)));
for (String line : lines) {
statements.add(appendToFile(line, path, family));
}
}
return new StatementList(statements).render(family);
}
private void hereFile(String path, StringBuilder builder) {
builder.append("cat > ").append(path).append(" <<'").append(MARKER).append("'\n");
for (String line : lines) {
builder.append(line).append("\n");
}
builder.append(MARKER).append("\n");
}
private Statement appendToFile(String line, String path, OsFamily family) {
String quote = "";
if (!ShellToken.VQ.to(family).equals("")) {
quote = "'";
} else {
line = escapeVarTokens(line, family);
}
return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
quote, path)));
}
public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");
static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) {
return REDIRECT_FD_PATTERN.matcher(line).matches() ? line.replace(">>", " >>") : line;
}
}

View File

@ -20,7 +20,6 @@
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.Preconditions.checkState;
import static org.jclouds.scriptbuilder.domain.Statements.interpret; import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import java.util.Collections; import java.util.Collections;
@ -48,19 +47,13 @@ public class CreateRunScript implements Statement {
final String instanceName; final String instanceName;
final Iterable<String> exports; final Iterable<String> exports;
final String pwd; final String pwd;
final String[] execLines; final Iterable<Statement> statements;
public CreateRunScript(String instanceName, Iterable<String> exports, String pwd, public CreateRunScript(String instanceName, Iterable<String> exports, String pwd, Iterable<Statement> statements) {
String... execLines) {// TODO: convert so
// that
// createRunScript
// can take from a
// variable
this.instanceName = checkNotNull(instanceName, "instanceName"); this.instanceName = checkNotNull(instanceName, "instanceName");
this.exports = checkNotNull(exports, "exports"); this.exports = checkNotNull(exports, "exports");
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}"); this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
this.execLines = checkNotNull(execLines, "execLines"); this.statements = checkNotNull(statements, "statements");
checkState(execLines.length > 0, "you must pass something to execute");
} }
public static class AddTitleToFile implements Statement { public static class AddTitleToFile implements Statement {
@ -72,10 +65,9 @@ public class CreateRunScript implements Statement {
this.file = checkNotNull(file, "file"); this.file = checkNotNull(file, "file");
} }
public static final Map<OsFamily, String> OS_TO_TITLE_PATTERN = ImmutableMap.of( public static final Map<OsFamily, String> OS_TO_TITLE_PATTERN = ImmutableMap.of(OsFamily.UNIX,
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", "echo title {title}>>{file}\r\n");
OsFamily.WINDOWS, "echo title {title}>>{file}\r\n");
@Override @Override
public Iterable<String> functionDependecies(OsFamily family) { public Iterable<String> functionDependecies(OsFamily family) {
@ -84,8 +76,8 @@ public class CreateRunScript implements Statement {
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens( return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_TITLE_PATTERN.get(family),
OS_TO_TITLE_PATTERN.get(family), ImmutableMap.of("title", title, "file", file))); ImmutableMap.of("title", title, "file", file)));
} }
} }
@ -95,14 +87,13 @@ public class CreateRunScript implements Statement {
final String file; final String file;
public AddExportToFile(String export, String value, String file) { public AddExportToFile(String export, String value, String file) {
this.export = checkNotNull(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export), this.export = checkNotNull(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export), "export");
"export");
this.value = checkNotNull(value, "value"); this.value = checkNotNull(value, "value");
this.file = checkNotNull(file, "file"); this.file = checkNotNull(file, "file");
} }
public static final Map<OsFamily, String> OS_TO_EXPORT_PATTERN = ImmutableMap.of( public static final Map<OsFamily, String> OS_TO_EXPORT_PATTERN = ImmutableMap.of(OsFamily.UNIX,
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
@ -112,9 +103,8 @@ public class CreateRunScript implements Statement {
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens( return addSpaceToEnsureWeDontAccidentallyRedirectFd(Utils.replaceTokens(OS_TO_EXPORT_PATTERN.get(family),
OS_TO_EXPORT_PATTERN.get(family), ImmutableMap.of("export", export, "value", ImmutableMap.of("export", export, "value", value, "file", file)));
value, "file", file)));
} }
} }
@ -137,8 +127,8 @@ public class CreateRunScript implements Statement {
return Collections.emptyList(); return Collections.emptyList();
} }
public static final Map<OsFamily, String> OS_TO_CHMOD_PATTERN = ImmutableMap.of(OsFamily.UNIX, public static final Map<OsFamily, String> OS_TO_CHMOD_PATTERN = ImmutableMap.of(OsFamily.UNIX, "chmod u+x {file}\n",
"chmod u+x {file}\n", OsFamily.WINDOWS, ""); OsFamily.WINDOWS, "");
@Override @Override
public String render(OsFamily family) { public String render(OsFamily family) {
@ -158,32 +148,29 @@ public class CreateRunScript implements Statement {
statements.add(interpret(builder.toString())); statements.add(interpret(builder.toString()));
} else { } else {
statements.add(interpret(String.format("{rm} %s 2{closeFd}{lf}", runScript))); statements.add(interpret(String.format("{rm} %s 2{closeFd}{lf}", runScript)));
for (String line : Splitter.on(ShellToken.LF.to(family)).split( for (String line : Splitter.on(ShellToken.LF.to(family)).split(ShellToken.BEGIN_SCRIPT.to(family))) {
ShellToken.BEGIN_SCRIPT.to(family))) {
if (!line.equals("")) if (!line.equals(""))
statements.add(appendToFile(line, runScript, family)); statements.add(appendToFile(line, runScript, family));
} }
statements.add(new AddTitleToFile(instanceName, runScript)); statements.add(new AddTitleToFile(instanceName, runScript));
statements.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family), statements.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family), ""), runScript,
""), 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.add(new AddExportToFile(export, Utils.replaceTokens("{varl}" statements
+ CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}", .add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
tokenMap), runScript)); + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}", tokenMap),
runScript));
} }
statements.add(appendToFile("{cd} " + pwd, runScript, family)); statements.add(appendToFile("{cd} " + pwd, runScript, family));
for (String execLine : execLines) { statements.addAll(statements);
statements.add(appendToFile(execLine, runScript, family)); for (String line : Splitter.on(ShellToken.LF.to(family)).split(ShellToken.END_SCRIPT.to(family))) {
}
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
ShellToken.END_SCRIPT.to(family))) {
if (!line.equals("")) if (!line.equals(""))
statements.add(appendToFile(line, runScript, family)); statements.add(appendToFile(line, runScript, family));
} }
} }
statements.add(interpret(Utils.replaceTokens(OS_TO_CHMOD_PATTERN.get(family), ImmutableMap statements
.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);
} }
@ -198,8 +185,8 @@ public class CreateRunScript implements Statement {
builder.append("# add desired commands from the user\n"); builder.append("# add desired commands from the user\n");
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 (String execLine : execLines) { for (Statement statement : statements) {
builder.append(execLine).append("\n"); builder.append(statement.render(OsFamily.UNIX)).append("\n");
} }
builder.append(MARKER).append("\n"); builder.append(MARKER).append("\n");
} }
@ -208,15 +195,12 @@ public class CreateRunScript implements Statement {
builder.append("# create runscript header\n"); builder.append("# create runscript header\n");
builder.append("cat > ").append(runScript).append(" <<").append(MARKER).append("\n"); builder.append("cat > ").append(runScript).append(" <<").append(MARKER).append("\n");
builder.append(ShellToken.BEGIN_SCRIPT.to(family)); builder.append(ShellToken.BEGIN_SCRIPT.to(family));
builder.append("PROMPT_COMMAND='echo -ne \"\\033]0;").append(instanceName).append( builder.append("PROMPT_COMMAND='echo -ne \"\\033]0;").append(instanceName).append("\\007\"'\n");
"\\007\"'\n");
builder.append(Utils.writeZeroPath(family)); builder.append(Utils.writeZeroPath(family));
builder.append("export INSTANCE_NAME='").append(instanceName).append("'\n"); builder.append("export INSTANCE_NAME='").append(instanceName).append("'\n");
for (String export : exports) { for (String export : exports) {
String variableNameInUpper = CaseFormat.LOWER_CAMEL String variableNameInUpper = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export);
.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");
} }
builder.append(MARKER).append("\n"); builder.append(MARKER).append("\n");
} }
@ -228,8 +212,8 @@ public class CreateRunScript implements Statement {
} else { } else {
line = escapeVarTokens(line, family); line = escapeVarTokens(line, family);
} }
return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format( return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
"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

@ -21,8 +21,11 @@ package org.jclouds.scriptbuilder.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import org.jclouds.scriptbuilder.util.Utils; import org.jclouds.scriptbuilder.util.Utils;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
/** /**
@ -32,14 +35,15 @@ import com.google.common.collect.ImmutableList;
*/ */
public class InterpretableStatement implements Statement { public class InterpretableStatement implements Statement {
private String statement; private String[] statements;
public InterpretableStatement(String statement) { public InterpretableStatement(String... statements) {
this.statement = checkNotNull(statement, "statement"); this.statements = checkNotNull(statements, "statements");
} }
public String render(OsFamily family) { public String render(OsFamily family) {
return Utils.replaceTokens(statement, ShellToken.tokenValueMap(family)); return Utils
.replaceTokens(Joiner.on(ShellToken.LF.to(family)).join(statements), ShellToken.tokenValueMap(family));
} }
@Override @Override
@ -51,7 +55,7 @@ public class InterpretableStatement implements Statement {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + ((statement == null) ? 0 : statement.hashCode()); result = prime * result + Arrays.hashCode(statements);
return result; return result;
} }
@ -64,10 +68,7 @@ public class InterpretableStatement implements Statement {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
InterpretableStatement other = (InterpretableStatement) obj; InterpretableStatement other = (InterpretableStatement) obj;
if (statement == null) { if (!Arrays.equals(statements, other.statements))
if (other.statement != null)
return false;
} else if (!statement.equals(other.statement))
return false; return false;
return true; return true;
} }

View File

@ -41,13 +41,17 @@ public class Statements {
return new Call(function, args); return new Call(function, args);
} }
public static Statement createRunScript(String instanceName, Iterable<String> exports, public static Statement createFile(String path, Iterable<String> lines) {
String pwd, String... execLines) {// TODO: convert so return new CreateFile(path, lines);
}
public static Statement createRunScript(String instanceName, Iterable<String> exports, String pwd,
Iterable<Statement> statements) {// TODO: convert so
// that // that
// createRunScript // createRunScript
// can take from a // can take from a
// variable // variable
return new CreateRunScript(instanceName, exports, pwd, execLines); return new CreateRunScript(instanceName, exports, pwd, statements);
} }
/** /**
@ -89,18 +93,18 @@ public class Statements {
} }
/** /**
* statement can have multiple newlines, note you should use {@code {lf} } to be portable * statement can have multiple newlines, note you should use {@code lf} to be portable
* *
* @see ShellToken * @see ShellToken
*/ */
public static Statement interpret(String portableStatement) { public static Statement interpret(String ... portableStatements) {
return new InterpretableStatement(portableStatement); return new InterpretableStatement(portableStatements);
} }
/** /**
* interprets and adds a newline to the statement * interprets and adds a newline to the statement
*/ */
public static Statement exec(String portableStatement) { public static Statement exec(String portableStatement) {
return interpret(portableStatement+"{lf}"); return interpret(portableStatement + "{lf}");
} }
} }

View File

@ -43,15 +43,14 @@ public class SwitchArg implements Statement {
private static final String INDENT = " "; private static final String INDENT = " ";
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 ${arg} in\n",
"case ${arg} in\n", OsFamily.WINDOWS, "goto CASE_%{arg}\r\n"); OsFamily.WINDOWS, "goto CASE_%{arg}\r\n");
public static final Map<OsFamily, String> OS_TO_END_SWITCH_PATTERN = ImmutableMap.of( public static final Map<OsFamily, String> OS_TO_END_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX, "esac\n",
OsFamily.UNIX, "esac\n", OsFamily.WINDOWS, ":END_SWITCH\r\n"); OsFamily.WINDOWS, ":END_SWITCH\r\n");
public static final Map<OsFamily, String> OS_TO_CASE_PATTERN = ImmutableMap.of(OsFamily.UNIX, public static final Map<OsFamily, String> OS_TO_CASE_PATTERN = ImmutableMap.of(OsFamily.UNIX,
"{value})\n{action};;\n", OsFamily.WINDOWS, "{value})\n{action};;\n", OsFamily.WINDOWS, ":CASE_{value}\r\n{action}GOTO END_SWITCH\r\n");
":CASE_{value}\r\n{action}GOTO END_SWITCH\r\n");
private final int arg; private final int arg;
@ -84,26 +83,31 @@ public class SwitchArg implements Statement {
public String render(OsFamily family) { public String render(OsFamily family) {
StringBuilder switchClause = new StringBuilder(); StringBuilder switchClause = new StringBuilder();
addArgValidation(switchClause, family); addArgValidation(switchClause, family);
switchClause.append(Utils.replaceTokens(OS_TO_SWITCH_PATTERN.get(family), ImmutableMap.of( switchClause.append(Utils.replaceTokens(OS_TO_SWITCH_PATTERN.get(family), ImmutableMap.of("arg", arg + "")));
"arg", arg + "")));
for (Entry<String, Statement> entry : valueToActions.entrySet()) { for (Entry<String, Statement> entry : valueToActions.entrySet()) {
StringBuilder actionBuilder = new StringBuilder(); StringBuilder actionBuilder = new StringBuilder();
boolean shouldIndent = true;
boolean inRunScript = false; boolean inRunScript = false;
for (String line : Splitter.on(ShellToken.LF.to(family)).split( boolean inCreateFile = false;
entry.getValue().render(family))) { for (String line : Splitter.on(ShellToken.LF.to(family)).split(entry.getValue().render(family))) {
if (!inRunScript) if (shouldIndent)
actionBuilder.append(INDENT); actionBuilder.append(INDENT);
actionBuilder.append(line).append(ShellToken.LF.to(family)); actionBuilder.append(line).append(ShellToken.LF.to(family));
if (line.indexOf(CreateRunScript.MARKER) != -1) { if (line.indexOf(CreateRunScript.MARKER) != -1) {
inRunScript = inRunScript ? false : true; inRunScript = inRunScript ? false : true;
} }
if (line.indexOf(CreateFile.MARKER) != -1) {
inCreateFile = inCreateFile ? false : true;
} }
actionBuilder.delete(actionBuilder.lastIndexOf(ShellToken.LF.to(family)), actionBuilder shouldIndent = !inCreateFile && !inRunScript;
.length());
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of( }
"value", entry.getKey(), "action", actionBuilder.toString()))); actionBuilder.delete(actionBuilder.lastIndexOf(ShellToken.LF.to(family)), actionBuilder.length());
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of("value", entry
.getKey(), "action", actionBuilder.toString())));
} }
switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family)); switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family));
@ -114,11 +118,9 @@ public class SwitchArg implements Statement {
void addArgValidation(StringBuilder switchClause, OsFamily family) { void addArgValidation(StringBuilder switchClause, OsFamily family) {
if (family.equals(OsFamily.WINDOWS)) { if (family.equals(OsFamily.WINDOWS)) {
for (String value : valueToActions.keySet()) { for (String value : valueToActions.keySet()) {
switchClause.append("if not \"%").append(arg).append( switchClause.append("if not \"%").append(arg).append(String.format("\" == \"%s\" ", value));
String.format("\" == \"%s\" ", value));
} }
switchClause.append("(\r\n set EXCEPTION=bad argument: %").append(arg) switchClause.append("(\r\n set EXCEPTION=bad argument: %").append(arg).append(" not in ");
.append(" not in ");
switchClause.append(Joiner.on(" ").join(valueToActions.keySet())); switchClause.append(Joiner.on(" ").join(valueToActions.keySet()));
switchClause.append("\r\n goto abort\r\n)\r\n"); switchClause.append("\r\n goto abort\r\n)\r\n");
} }

View File

@ -19,6 +19,8 @@
package org.jclouds.scriptbuilder; package org.jclouds.scriptbuilder;
import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.createFile;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
@ -26,9 +28,12 @@ import java.net.MalformedURLException;
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.Statements;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharStreams; import com.google.common.io.CharStreams;
import com.google.common.io.Resources; import com.google.common.io.Resources;
@ -40,21 +45,20 @@ import com.google.common.io.Resources;
*/ */
public class InitBuilderTest { public class InitBuilderTest {
InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap InitBuilder testInitBuilder = new InitBuilder("mkebsboot", "/mnt/tmp", "/mnt/tmp", ImmutableMap.of("tmpDir",
.of("tmpDir", "/mnt/tmp"), "find /"); "/mnt/tmp"), ImmutableList.<Statement> of(
createFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList.<String> of("hello world")), call("find /")));
@Test @Test
public void testBuildSimpleWindows() throws MalformedURLException, IOException { public void testBuildSimpleWindows() throws MalformedURLException, IOException {
assertEquals(testInitBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources assertEquals(testInitBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_init." .getResource("test_init." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testBuildSimpleUNIX() throws MalformedURLException, IOException { public void testBuildSimpleUNIX() throws MalformedURLException, IOException {
assertEquals(testInitBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources assertEquals(testInitBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_init." .getResource("test_init." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
@Test @Test
@ -64,9 +68,13 @@ public class InitBuilderTest {
"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", ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables
"ebsMountPoint", "/mnt/ebs"),// variables used inside of the script // used
"echo creating a filesystem and mounting the ebs volume",// what to execute // inside
// of
// the
// script
ImmutableList.<Statement> of(Statements.interpret("echo creating a filesystem and mounting the ebs volume",// what to execute
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}", "{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
"rm -rf {varl}IMAGE_DIR{varr}/*", "rm -rf {varl}IMAGE_DIR{varr}/*",
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-", "yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
@ -75,17 +83,11 @@ public class InitBuilderTest {
"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}", "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}",
"echo preparing the local working copy", "echo preparing the local working copy",
"touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
"echo copying the local working copy to the ebs mount", "echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}",
"{cd} {varl}IMAGE_DIR{varr}", "tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}",
"echo size of ebs", "rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo ----COMPLETE----")
"du -sk {varl}EBS_MOUNT_POINT{varr}", )).build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
"echo size of source", .getResource("test_ebs." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
"du -sk {varl}IMAGE_DIR{varr}",
"rm -rf {varl}IMAGE_DIR{varr}/*",
"umount {varl}EBS_MOUNT_POINT{varr}", "echo ----COMPLETE----")
.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(
Resources.getResource("test_ebs." + ShellToken.SH.to(OsFamily.UNIX)),
Charsets.UTF_8)));
} }
} }

View File

@ -20,6 +20,7 @@
package org.jclouds.scriptbuilder; package org.jclouds.scriptbuilder;
import static org.jclouds.scriptbuilder.domain.Statements.call; import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.createFile;
import static org.jclouds.scriptbuilder.domain.Statements.findPid; 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;
@ -57,28 +58,27 @@ public class ScriptBuilderTest {
ImmutableMap ImmutableMap
.of( .of(
"start", "start",
newStatementList( newStatementList(call("default"),
call("default"),
interpret("echo start {varl}RUNTIME{varr}{lf}")), interpret("echo start {varl}RUNTIME{varr}{lf}")),
"stop", "stop",
newStatementList( newStatementList(call("default"),
call("default"),
interpret("echo stop {varl}RUNTIME{varr}{lf}")), interpret("echo stop {varl}RUNTIME{varr}{lf}")),
"status", "status",
newStatementList(interpret("echo {vq}the following should be []: [{varl}RUNTIME{varr}]{vq}{lf}"))))); newStatementList(
createFile("{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.build(OsFamily.WINDOWS), CharStreams.toString(Resources assertEquals(testScriptBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(
.newReaderSupplier(Resources.getResource("test_script." Resources.getResource("test_script." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testBuildSimpleUNIX() throws MalformedURLException, IOException { public void testBuildSimpleUNIX() throws MalformedURLException, IOException {
assertEquals(testScriptBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources assertEquals(testScriptBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_script." .getResource("test_script." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
ScriptBuilder findPidBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement( ScriptBuilder findPidBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement(
@ -86,40 +86,35 @@ public class ScriptBuilderTest {
@Test @Test
public void testFindPidWindows() throws MalformedURLException, IOException { public void testFindPidWindows() throws MalformedURLException, IOException {
assertEquals(findPidBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources assertEquals(findPidBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_find_pid." .getResource("test_find_pid." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testFindPidUNIX() throws MalformedURLException, IOException { public void testFindPidUNIX() throws MalformedURLException, IOException {
assertEquals(findPidBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources assertEquals(findPidBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_find_pid." .getResource("test_find_pid." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
ScriptBuilder seekAndDestroyBuilder = new ScriptBuilder().addStatement(findPid("{args}")) ScriptBuilder seekAndDestroyBuilder = new ScriptBuilder().addStatement(findPid("{args}")).addStatement(kill());
.addStatement(kill());
@Test @Test
public void testSeekAndDestroyWindows() throws MalformedURLException, IOException { public void testSeekAndDestroyWindows() throws MalformedURLException, IOException {
assertEquals(seekAndDestroyBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources assertEquals(seekAndDestroyBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(
.newReaderSupplier(Resources.getResource("test_seek_and_destroy." Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
@Test @Test
public void testSeekAndDestroyUNIX() throws MalformedURLException, IOException { public void testSeekAndDestroyUNIX() throws MalformedURLException, IOException {
assertEquals(seekAndDestroyBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources assertEquals(seekAndDestroyBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(
.newReaderSupplier(Resources.getResource("test_seek_and_destroy." Resources.getResource("test_seek_and_destroy." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
+ 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}"), builder.addStatement(switchArg(1, ImmutableMap.of("start", interpret("echo started{lf}"), "stop",
"stop", interpret("echo stopped{lf}")))); 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}")))));
} }
@ -134,8 +129,7 @@ public class ScriptBuilderTest {
public void testExport() { public void testExport() {
ScriptBuilder builder = new ScriptBuilder(); ScriptBuilder builder = new ScriptBuilder();
builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6")); builder.addEnvironmentVariableScope("default", ImmutableMap.of("javaHome", "/apps/jdk1.6"));
assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("javaHome", assertEquals(builder.variableScopes, ImmutableMap.of("default", ImmutableMap.of("javaHome", "/apps/jdk1.6")));
"/apps/jdk1.6")));
} }
@Test @Test

View File

@ -0,0 +1,59 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.scriptbuilder.domain.Statements.createFile;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "scriptbuilder.CreateFileTest")
public class CreateFileTest {
Statement statement = createFile("{root}etc{fs}chef{fs}client.rb", ImmutableList.of("log_level :info",
"log_location STDOUT", String.format("chef_server_url \"%s\"", "http://localhost:4000")));
public void testUNIX() throws IOException {
assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
}
public void testWINDOWS() throws IOException {
assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
}
public void testRedirectGuard() {
assertEquals(CreateFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>");
assertEquals(CreateFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"), "foo0 >>");
assertEquals(CreateFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"), "foo1 >>");
assertEquals(CreateFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"), "foo2 >>");
}
}

View File

@ -19,6 +19,8 @@
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.createFile;
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;
@ -36,30 +38,32 @@ import com.google.common.io.Resources;
*/ */
@Test(groups = "unit", testName = "scriptbuilder.CreateRunScriptTest") @Test(groups = "unit", testName = "scriptbuilder.CreateRunScriptTest")
public class CreateRunScriptTest { public class CreateRunScriptTest {
Statement statement = createRunScript("yahooprod", ImmutableList.<String> of("javaHome"), Statement statement = createRunScript(
"{tmp}{fs}{uid}{fs}scripttest", "echo hello", "yahooprod",
"echo {varl}JAVA_HOME{varr}{fs}bin{fs}java -DinstanceName={varl}INSTANCE_NAME{varr} myServer.Main"); ImmutableList.<String> of("javaHome"),
"{tmp}{fs}{uid}{fs}scripttest",
ImmutableList
.<Statement> of(
call("echo hello"),
createFile("{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", ImmutableList
.<String> of("hello world")),
call("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 assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_runrun." .getResource("test_runrun." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
} }
public void testWINDOWS() throws IOException { public void testWINDOWS() throws IOException {
assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.newReaderSupplier(Resources.getResource("test_runrun." .getResource("test_runrun." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
+ ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
} }
public void testRedirectGuard() { public void testRedirectGuard() {
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>"); assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>");
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"), assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"), "foo0 >>");
"foo0 >>"); assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"), "foo1 >>");
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"), assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"), "foo2 >>");
"foo1 >>");
assertEquals(CreateRunScript.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"),
"foo2 >>");
} }
} }

View File

@ -19,10 +19,15 @@
package org.jclouds.scriptbuilder.domain; package org.jclouds.scriptbuilder.domain;
import static org.jclouds.scriptbuilder.domain.Statements.createFile;
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Collections;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.jclouds.scriptbuilder.domain.Statements.*;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
/** /**
@ -32,9 +37,10 @@ import com.google.common.collect.ImmutableMap;
public class SwitchArgTest { public class SwitchArgTest {
public void testSwitchArgUNIX() { public void testSwitchArgUNIX() {
assertEquals(new SwitchArg(1, ImmutableMap.of("0", interpret("echo hello zero{lf}"), "1", assertEquals(new SwitchArg(1, ImmutableMap.of("0", newStatementList(createFile(
interpret("echo hello one{lf}"))).render(OsFamily.UNIX), "{tmp}{fs}{uid}{fs}scripttest{fs}temp.txt", Collections.singleton("hello world")),
"case $1 in\n0)\n echo hello zero\n ;;\n1)\n echo hello one\n ;;\nesac\n"); interpret("echo hello zero{lf}")), "1", interpret("echo hello one{lf}"))).render(OsFamily.UNIX),
"case $1 in\n0)\n cat > /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'\nhello world\nEND_OF_FILE\n echo hello zero\n ;;\n1)\n echo hello one\n ;;\nesac\n");
} }
public void testSwitchArgWindows() { public void testSwitchArgWindows() {

View File

@ -0,0 +1,4 @@
del c:\etc\chef\client.rb 2>NUL
echo log_level :info>>c:\etc\chef\client.rb
echo log_location STDOUT>>c:\etc\chef\client.rb
echo chef_server_url "http://localhost:4000">>c:\etc\chef\client.rb

View File

@ -0,0 +1,5 @@
cat > /etc/chef/client.rb <<'END_OF_FILE'
log_level :info
log_location STDOUT
chef_server_url "http://localhost:4000"
END_OF_FILE

View File

@ -80,7 +80,17 @@ goto CASE_%1
echo set INSTANCE_HOME=%INSTANCE_HOME%>>%INSTANCE_HOME%\mkebsboot.cmd echo set INSTANCE_HOME=%INSTANCE_HOME%>>%INSTANCE_HOME%\mkebsboot.cmd
echo set LOG_DIR=%LOG_DIR%>>%INSTANCE_HOME%\mkebsboot.cmd echo set LOG_DIR=%LOG_DIR%>>%INSTANCE_HOME%\mkebsboot.cmd
echo cd /d %%INSTANCE_HOME%%>>%INSTANCE_HOME%\mkebsboot.cmd echo cd /d %%INSTANCE_HOME%%>>%INSTANCE_HOME%\mkebsboot.cmd
echo find />>%INSTANCE_HOME%\mkebsboot.cmd md %INSTANCE_HOME%
del %INSTANCE_HOME%\mkebsboot.cmd 2>NUL
echo @echo off>>%INSTANCE_HOME%\mkebsboot.cmd
echo title mkebsboot>>%INSTANCE_HOME%\mkebsboot.cmd
echo set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem>>%INSTANCE_HOME%\mkebsboot.cmd
echo set INSTANCE_NAME=mkebsboot>>%INSTANCE_HOME%\mkebsboot.cmd
echo set TMP_DIR=%TMP_DIR%>>%INSTANCE_HOME%\mkebsboot.cmd
echo set INSTANCE_NAME=%INSTANCE_NAME%>>%INSTANCE_HOME%\mkebsboot.cmd
echo set INSTANCE_HOME=%INSTANCE_HOME%>>%INSTANCE_HOME%\mkebsboot.cmd
echo set LOG_DIR=%LOG_DIR%>>%INSTANCE_HOME%\mkebsboot.cmd
echo cd /d %%INSTANCE_HOME%%>>%INSTANCE_HOME%\mkebsboot.cmd
echo exit /b 0 >>%INSTANCE_HOME%\mkebsboot.cmd echo exit /b 0 >>%INSTANCE_HOME%\mkebsboot.cmd
GOTO END_SWITCH GOTO END_SWITCH
:CASE_status :CASE_status

View File

@ -78,7 +78,12 @@ END_OF_SCRIPT
# add desired commands from the user # add desired commands from the user
cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT' cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT'
cd $INSTANCE_HOME cd $INSTANCE_HOME
find / cat > /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'
hello world
END_OF_FILE
find / || exit 1
END_OF_SCRIPT END_OF_SCRIPT
# add runscript footer # add runscript footer

View File

@ -6,6 +6,12 @@ echo set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem>>%TEMP%\%
echo set INSTANCE_NAME=yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd echo set INSTANCE_NAME=yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo set JAVA_HOME=%JAVA_HOME%>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd echo set JAVA_HOME=%JAVA_HOME%>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo cd /d %TEMP%\%USERNAME%\scripttest>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd echo cd /d %TEMP%\%USERNAME%\scripttest>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo echo hello>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd md %TEMP%\%USERNAME%\scripttest
echo echo %%JAVA_HOME%%\bin\java -DinstanceName=%%INSTANCE_NAME%% myServer.Main>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd del %TEMP%\%USERNAME%\scripttest\yahooprod.cmd 2>NUL
echo @echo off>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo title yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo set INSTANCE_NAME=yahooprod>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo set JAVA_HOME=%JAVA_HOME%>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo cd /d %TEMP%\%USERNAME%\scripttest>>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd
echo exit /b 0 >>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd echo exit /b 0 >>%TEMP%\%USERNAME%\scripttest\yahooprod.cmd

View File

@ -15,8 +15,14 @@ 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 echo hello || return 1
echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main
cat > /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'
hello world
END_OF_FILE
echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main || return 1
END_OF_SCRIPT END_OF_SCRIPT
# add runscript footer # add runscript footer

View File

@ -28,6 +28,8 @@ goto CASE_%1
echo stop %RUNTIME% echo stop %RUNTIME%
GOTO END_SWITCH GOTO END_SWITCH
:CASE_status :CASE_status
del %TEMP%\%USERNAME%\scripttest\temp.txt 2>NUL
echo hello world>>%TEMP%\%USERNAME%\scripttest\temp.txt
echo the following should be []: [%RUNTIME%] echo the following should be []: [%RUNTIME%]
GOTO END_SWITCH GOTO END_SWITCH
:END_SWITCH :END_SWITCH

View File

@ -22,6 +22,9 @@ stop)
echo stop $RUNTIME echo stop $RUNTIME
;; ;;
status) status)
cat > /tmp/$USER/scripttest/temp.txt <<'END_OF_FILE'
hello world
END_OF_FILE
echo "the following should be []: [$RUNTIME]" echo "the following should be []: [$RUNTIME]"
;; ;;
esac esac

View File

@ -53,6 +53,7 @@ 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.StatementList; import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.tools.ant.util.SSHExecute; import org.jclouds.tools.ant.util.SSHExecute;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -130,8 +131,7 @@ public class SSHJava extends Java {
if (remotedir == null) if (remotedir == null)
remotedir = new File(remotebase, id); remotedir = new File(remotebase, id);
String command = createInitScript(osFamily, id, remotedir.getAbsolutePath(), env, String command = createInitScript(osFamily, id, remotedir.getAbsolutePath(), env, getCommandLine());
getCommandLine());
try { try {
BufferedWriter out = new BufferedWriter(new FileWriter(new File(localDirectory, "init." BufferedWriter out = new BufferedWriter(new FileWriter(new File(localDirectory, "init."
@ -159,8 +159,8 @@ public class SSHJava extends Java {
File source = new File(entry.getKey()); File source = new File(entry.getKey());
if (source.isDirectory()) { if (source.isDirectory()) {
set.setDir(new File(entry.getKey())); set.setDir(new File(entry.getKey()));
mkdirAndCopyTo(remotebase.getAbsolutePath() + ShellToken.FS.to(osFamily) mkdirAndCopyTo(remotebase.getAbsolutePath() + ShellToken.FS.to(osFamily) + entry.getValue(), ImmutableList
+ entry.getValue(), ImmutableList.of(set)); .of(set));
} else { } else {
String destination = remotebase.getAbsolutePath() + ShellToken.FS.to(osFamily) String destination = remotebase.getAbsolutePath() + ShellToken.FS.to(osFamily)
+ new File(entry.getValue()).getParent(); + new File(entry.getValue()).getParent();
@ -179,19 +179,16 @@ public class SSHJava extends Java {
} }
if (getCommandLine().getBootclasspath() != null) { if (getCommandLine().getBootclasspath() != null) {
copyPathTo(getCommandLine().getBootclasspath(), remotedir.getAbsolutePath() copyPathTo(getCommandLine().getBootclasspath(), remotedir.getAbsolutePath() + "/bootclasspath");
+ "/bootclasspath");
} }
if (osFamily == OsFamily.UNIX) { if (osFamily == OsFamily.UNIX) {
sshexec(exec("chmod 755 " + remotedir.getAbsolutePath() + "{fs}init.{sh}") sshexec(exec("chmod 755 " + remotedir.getAbsolutePath() + "{fs}init.{sh}").render(osFamily));
.render(osFamily));
} }
Statement statement = new StatementList(exec("{cd} " + remotedir.getAbsolutePath()), Statement statement = new StatementList(exec("{cd} " + remotedir.getAbsolutePath()), exec(remotedir
exec(remotedir.getAbsolutePath() + "{fs}init.{sh} init"), exec(remotedir
.getAbsolutePath() .getAbsolutePath()
+ "{fs}init.{sh} run")); + "{fs}init.{sh} init"), exec(remotedir.getAbsolutePath() + "{fs}init.{sh} run"));
try { try {
return sshexecRedirectStreams(statement); return sshexecRedirectStreams(statement);
} catch (IOException e) { } catch (IOException e) {
@ -270,13 +267,11 @@ public class SSHJava extends Java {
} }
private String getScpDir(String path) { private String getScpDir(String path) {
return String.format("%s:%s@%s:%s", userInfo.getName(), return String.format("%s:%s@%s:%s", userInfo.getName(), userInfo.getKeyfile() == null ? userInfo.getPassword()
userInfo.getKeyfile() == null ? userInfo.getPassword() : userInfo.getPassphrase(), : userInfo.getPassphrase(), scp.getHost(), path);
scp.getHost(), path);
} }
void resetPathToUnderPrefixIfExistsAndIsFileIfNotExistsAddAsIs(Path path, String prefix, void resetPathToUnderPrefixIfExistsAndIsFileIfNotExistsAddAsIs(Path path, String prefix, StringBuilder destination) {
StringBuilder destination) {
if (path == null) if (path == null)
return; return;
String[] paths = path.list(); String[] paths = path.list();
@ -324,8 +319,7 @@ public class SSHJava extends Java {
for (Entry<String, String> entry : shiftMap.entrySet()) { for (Entry<String, String> entry : shiftMap.entrySet()) {
if (in.startsWith(entry.getKey())) { if (in.startsWith(entry.getKey())) {
log("match shift map: " + entry.getKey(), Project.MSG_DEBUG); log("match shift map: " + entry.getKey(), Project.MSG_DEBUG);
in = remotebase + ShellToken.FS.to(osFamily) + entry.getValue() in = remotebase + ShellToken.FS.to(osFamily) + entry.getValue() + in.substring(entry.getKey().length());
+ in.substring(entry.getKey().length());
} }
} }
for (Entry<String, String> entry : replace.entrySet()) { for (Entry<String, String> entry : replace.entrySet()) {
@ -381,7 +375,7 @@ public class SSHJava extends Java {
} }
InitBuilder testInitBuilder = new InitBuilder(id, basedir, basedir, envVariables, InitBuilder testInitBuilder = new InitBuilder(id, basedir, basedir, envVariables,
commandBuilder.toString()); ImmutableList.<Statement> of(Statements.interpret( commandBuilder.toString())));
return testInitBuilder.build(osFamily); return testInitBuilder.build(osFamily);
} }
@ -560,11 +554,10 @@ public class SSHJava extends Java {
@Override @Override
public String toString() { public String toString() {
return "SSHJava [append=" + append + ", env=" + env + ", errorFile=" + errorFile return "SSHJava [append=" + append + ", env=" + env + ", errorFile=" + errorFile + ", errorProperty="
+ ", errorProperty=" + errorProperty + ", localDirectory=" + localDirectory + errorProperty + ", localDirectory=" + localDirectory + ", osFamily=" + osFamily + ", outputFile="
+ ", osFamily=" + osFamily + ", outputFile=" + outputFile + ", outputProperty=" + outputFile + ", outputProperty=" + outputProperty + ", remoteDirectory=" + remotebase + ", userInfo="
+ outputProperty + ", remoteDirectory=" + remotebase + ", userInfo=" + userInfo + userInfo + "]";
+ "]";
} }
@Override @Override