tuned runscript to use herefile syntax so that it is easier to troubleshoot and works without needing to escape characters

This commit is contained in:
Adrian Cole 2010-04-06 15:13:08 -07:00
parent c352f408a2
commit fab4a0fb4d
9 changed files with 246 additions and 103 deletions

View File

@ -28,6 +28,8 @@ import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
@ -42,7 +44,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test
public void testTemplateBuilderCanUseImageId() {
client.templateBuilder().imageId("ami-d57f93bc").build();
client.templateBuilder().imageId(Iterables.get(client.getImages().keySet(), 0)).build();
}
@Test

View File

@ -89,17 +89,17 @@ public class InitBuilder extends ScriptBuilder {
"tail",
newStatementList(
call("default"),
interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log")))
interpret("tail {varl}LOG_DIR{varr}{fs}stdout.log{lf}")))
.put(
"tailerr",
newStatementList(
call("default"),
interpret("tail {varl}LOG_DIR{varr}{fs}stderr.log")))
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}")))
interpret("{varl}INSTANCE_HOME{varr}{fs}{varl}INSTANCE_NAME{varr}.{sh}{lf}")))
.build()));
}
}

View File

@ -19,6 +19,7 @@
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;
@ -42,6 +43,7 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*/
public class CreateRunScript implements Statement {
public final static String MARKER = "END_OF_SCRIPT";
final String instanceName;
final Iterable<String> exports;
final String pwd;
@ -57,6 +59,7 @@ public class CreateRunScript implements Statement {
this.exports = checkNotNull(exports, "exports");
this.pwd = checkNotNull(pwd, "pwd").replaceAll("[/\\\\]", "{fs}");
this.execLines = checkNotNull(execLines, "execLines");
checkState(execLines.length > 0, "you must pass something to execute");
}
public static class AddTitleToFile implements Statement {
@ -142,36 +145,81 @@ public class CreateRunScript implements Statement {
Map<String, String> tokenMap = ShellToken.tokenValueMap(family);
String runScript = Utils.replaceTokens(pwd + "{fs}" + instanceName + ".{sh}", tokenMap);
statements.add(interpret(String.format("{md} %s{lf}", pwd)));
statements.add(interpret(String.format("{rm} %s 2{closeFd}{lf}", runScript)));
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
ShellToken.BEGIN_SCRIPT.to(family))) {
if (!line.equals(""))
statements.add(appendToFile(line, runScript, family));
}
statements.add(new AddTitleToFile(instanceName, runScript));
statements
.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family), ""),
runScript, family));
statements.add(new AddExportToFile("instanceName", instanceName, runScript));
for (String export : exports) {
statements.add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
+ CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}",
tokenMap), runScript));
}
statements.add(appendToFile("{cd} " + pwd, runScript, family));
for (String execLine : execLines) {
statements.add(appendToFile(execLine, runScript, family));
}
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
ShellToken.END_SCRIPT.to(family))) {
if (!line.equals(""))
statements.add(appendToFile(line, runScript, family));
if (family == OsFamily.UNIX) {
StringBuilder builder = new StringBuilder();
builder.append("\n");
addUnixRunScriptHeader(family, runScript, builder);
builder.append("\n");
addUnixRunScript(runScript, builder);
builder.append("\n");
addUnixRunScriptFooter(family, runScript, builder);
builder.append("\n");
statements.add(interpret(builder.toString()));
} else {
statements.add(interpret(String.format("{rm} %s 2{closeFd}{lf}", runScript)));
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
ShellToken.BEGIN_SCRIPT.to(family))) {
if (!line.equals(""))
statements.add(appendToFile(line, runScript, family));
}
statements.add(new AddTitleToFile(instanceName, runScript));
statements.add(appendToFile(Utils.writeZeroPath(family).replace(ShellToken.LF.to(family),
""), runScript, family));
statements.add(new AddExportToFile("instanceName", instanceName, runScript));
for (String export : exports) {
statements.add(new AddExportToFile(export, Utils.replaceTokens("{varl}"
+ CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, export) + "{varr}",
tokenMap), runScript));
}
statements.add(appendToFile("{cd} " + pwd, runScript, family));
for (String execLine : execLines) {
statements.add(appendToFile(execLine, runScript, family));
}
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
ShellToken.END_SCRIPT.to(family))) {
if (!line.equals(""))
statements.add(appendToFile(line, runScript, family));
}
}
statements.add(interpret(Utils.replaceTokens(OS_TO_CHMOD_PATTERN.get(family), ImmutableMap
.of("file", runScript))));
return new StatementList(statements).render(family);
}
private void addUnixRunScriptFooter(OsFamily family, String runScript, StringBuilder builder) {
builder.append("# add runscript footer\n");
builder.append("cat >> ").append(runScript).append(" <<'").append(MARKER).append("'\n");
builder.append(ShellToken.END_SCRIPT.to(family));
builder.append(MARKER).append("\n");
}
private void addUnixRunScript(String runScript, StringBuilder builder) {
builder.append("# add desired commands from the user\n");
builder.append("cat >> ").append(runScript).append(" <<'").append(MARKER).append("'\n");
builder.append("cd ").append(pwd).append("\n");
for (String execLine : execLines) {
builder.append(execLine).append("\n");
}
builder.append(MARKER).append("\n");
}
private void addUnixRunScriptHeader(OsFamily family, String runScript, StringBuilder builder) {
builder.append("# create runscript header\n");
builder.append("cat > ").append(runScript).append(" <<").append(MARKER).append("\n");
builder.append(ShellToken.BEGIN_SCRIPT.to(family));
builder.append("PROMPT_COMMAND='echo -ne \"\\033]0;").append(instanceName).append(
"\\007\"'\n");
builder.append(Utils.writeZeroPath(family));
builder.append("export INSTANCE_NAME='").append(instanceName).append("'\n");
for (String export : exports) {
String variableNameInUpper = CaseFormat.LOWER_CAMEL
.to(CaseFormat.UPPER_UNDERSCORE, export);
builder.append("export ").append(variableNameInUpper).append("='$").append(
variableNameInUpper).append("'\n");
}
builder.append(MARKER).append("\n");
}
private Statement appendToFile(String line, String runScript, OsFamily family) {
String quote = "";
if (!ShellToken.VQ.to(family).equals("")) {

View File

@ -28,6 +28,7 @@ import org.jclouds.scriptbuilder.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@ -39,6 +40,8 @@ import com.google.common.collect.Lists;
*/
public class SwitchArg implements Statement {
private static final String INDENT = " ";
public static final Map<OsFamily, String> OS_TO_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX,
"case ${arg} in\n", OsFamily.WINDOWS, "goto CASE_%{arg}\r\n");
@ -84,10 +87,22 @@ public class SwitchArg implements Statement {
"arg", arg + "")));
for (Entry<String, Statement> entry : valueToActions.entrySet()) {
StringBuilder actionBuilder = new StringBuilder();
boolean inRunScript = false;
for (String line : Splitter.on(ShellToken.LF.to(family)).split(
entry.getValue().render(family))) {
if (!inRunScript)
actionBuilder.append(INDENT);
actionBuilder.append(line).append(ShellToken.LF.to(family));
if (line.indexOf(CreateRunScript.MARKER) != -1) {
inRunScript = inRunScript ? false : true;
}
}
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", entry.getValue().render(family).replaceAll(
"^", " ").replace(ShellToken.LF.to(family),
ShellToken.LF.to(family) + " "))));
"value", entry.getKey(), "action", actionBuilder.toString())));
}
switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family));

View File

@ -61,41 +61,53 @@ init)
default || exit 1
mkebsboot || exit 1
mkdir -p $INSTANCE_HOME
rm $INSTANCE_HOME/mkebsboot.sh 2>&-
echo '#!/bin/bash'>>$INSTANCE_HOME/mkebsboot.sh
echo 'set +u'>>$INSTANCE_HOME/mkebsboot.sh
echo 'shopt -s xpg_echo'>>$INSTANCE_HOME/mkebsboot.sh
echo 'shopt -s expand_aliases'>>$INSTANCE_HOME/mkebsboot.sh
echo "PROMPT_COMMAND='echo -ne \"\033]0;mkebsboot\007\"'">>$INSTANCE_HOME/mkebsboot.sh
echo 'export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin'>>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_NAME='mkebsboot'">>$INSTANCE_HOME/mkebsboot.sh
echo "export IMAGE_DIR='$IMAGE_DIR'">>$INSTANCE_HOME/mkebsboot.sh
echo "export EBS_DEVICE='$EBS_DEVICE'">>$INSTANCE_HOME/mkebsboot.sh
echo "export EBS_MOUNT_POINT='$EBS_MOUNT_POINT'">>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_NAME='$INSTANCE_NAME'">>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_HOME='$INSTANCE_HOME'">>$INSTANCE_HOME/mkebsboot.sh
echo "export LOG_DIR='$LOG_DIR'">>$INSTANCE_HOME/mkebsboot.sh
echo 'cd $INSTANCE_HOME'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo creating a filesystem and mounting the ebs volume'>>$INSTANCE_HOME/mkebsboot.sh
echo 'mkdir -p $IMAGE_DIR $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
echo 'rm -rf $IMAGE_DIR/*'>>$INSTANCE_HOME/mkebsboot.sh
echo 'yes| mkfs -t ext3 $EBS_DEVICE 2>&-'>>$INSTANCE_HOME/mkebsboot.sh
echo 'mount $EBS_DEVICE $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo making a local working copy of the boot disk'>>$INSTANCE_HOME/mkebsboot.sh
echo '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 / $IMAGE_DIR'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo preparing the local working copy'>>$INSTANCE_HOME/mkebsboot.sh
echo 'touch $IMAGE_DIR/etc/init.d/ec2-init-user-data'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo copying the local working copy to the ebs mount'>>$INSTANCE_HOME/mkebsboot.sh
echo 'cd $IMAGE_DIR'>>$INSTANCE_HOME/mkebsboot.sh
echo 'tar -cSf - * | tar xf - -C $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo size of ebs'>>$INSTANCE_HOME/mkebsboot.sh
echo 'du -sk $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo size of source'>>$INSTANCE_HOME/mkebsboot.sh
echo 'du -sk $IMAGE_DIR'>>$INSTANCE_HOME/mkebsboot.sh
echo 'rm -rf $IMAGE_DIR/*'>>$INSTANCE_HOME/mkebsboot.sh
echo 'umount $EBS_MOUNT_POINT'>>$INSTANCE_HOME/mkebsboot.sh
echo 'echo ----COMPLETE----'>>$INSTANCE_HOME/mkebsboot.sh
echo 'exit 0'>>$INSTANCE_HOME/mkebsboot.sh
# create runscript header
cat > $INSTANCE_HOME/mkebsboot.sh <<END_OF_SCRIPT
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
PROMPT_COMMAND='echo -ne "\033]0;mkebsboot\007"'
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
export INSTANCE_NAME='mkebsboot'
export IMAGE_DIR='$IMAGE_DIR'
export EBS_DEVICE='$EBS_DEVICE'
export EBS_MOUNT_POINT='$EBS_MOUNT_POINT'
export INSTANCE_NAME='$INSTANCE_NAME'
export INSTANCE_HOME='$INSTANCE_HOME'
export LOG_DIR='$LOG_DIR'
END_OF_SCRIPT
# add desired commands from the user
cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT'
cd $INSTANCE_HOME
echo creating a filesystem and mounting the ebs volume
mkdir -p $IMAGE_DIR $EBS_MOUNT_POINT
rm -rf $IMAGE_DIR/*
yes| mkfs -t ext3 $EBS_DEVICE 2>&-
mount $EBS_DEVICE $EBS_MOUNT_POINT
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 / $IMAGE_DIR
echo preparing the local working copy
touch $IMAGE_DIR/etc/init.d/ec2-init-user-data
echo copying the local working copy to the ebs mount
cd $IMAGE_DIR
tar -cSf - * | tar xf - -C $EBS_MOUNT_POINT
echo size of ebs
du -sk $EBS_MOUNT_POINT
echo size of source
du -sk $IMAGE_DIR
rm -rf $IMAGE_DIR/*
umount $EBS_MOUNT_POINT
echo ----COMPLETE----
END_OF_SCRIPT
# add runscript footer
cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT'
exit 0
END_OF_SCRIPT
chmod u+x $INSTANCE_HOME/mkebsboot.sh
;;
status)
@ -117,12 +129,15 @@ start)
;;
tail)
default || exit 1
tail $LOG_DIR/stdout.log;;
tail $LOG_DIR/stdout.log
;;
tailerr)
default || exit 1
tail $LOG_DIR/stderr.log;;
tail $LOG_DIR/stderr.log
;;
run)
default || exit 1
$INSTANCE_HOME/$INSTANCE_NAME.sh;;
$INSTANCE_HOME/$INSTANCE_NAME.sh
;;
esac
exit 0

View File

@ -108,14 +108,17 @@ goto CASE_%1
:CASE_tail
call :default
if errorlevel 1 goto abort
tail %LOG_DIR%\stdout.logGOTO END_SWITCH
tail %LOG_DIR%\stdout.log
GOTO END_SWITCH
:CASE_tailerr
call :default
if errorlevel 1 goto abort
tail %LOG_DIR%\stderr.logGOTO END_SWITCH
tail %LOG_DIR%\stderr.log
GOTO END_SWITCH
:CASE_run
call :default
if errorlevel 1 goto abort
%INSTANCE_HOME%\%INSTANCE_NAME%.cmdGOTO END_SWITCH
%INSTANCE_HOME%\%INSTANCE_NAME%.cmd
GOTO END_SWITCH
:END_SWITCH
exit /b 0

View File

@ -59,21 +59,33 @@ init)
default || exit 1
mkebsboot || exit 1
mkdir -p $INSTANCE_HOME
rm $INSTANCE_HOME/mkebsboot.sh 2>&-
echo '#!/bin/bash'>>$INSTANCE_HOME/mkebsboot.sh
echo 'set +u'>>$INSTANCE_HOME/mkebsboot.sh
echo 'shopt -s xpg_echo'>>$INSTANCE_HOME/mkebsboot.sh
echo 'shopt -s expand_aliases'>>$INSTANCE_HOME/mkebsboot.sh
echo "PROMPT_COMMAND='echo -ne \"\033]0;mkebsboot\007\"'">>$INSTANCE_HOME/mkebsboot.sh
echo 'export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin'>>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_NAME='mkebsboot'">>$INSTANCE_HOME/mkebsboot.sh
echo "export TMP_DIR='$TMP_DIR'">>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_NAME='$INSTANCE_NAME'">>$INSTANCE_HOME/mkebsboot.sh
echo "export INSTANCE_HOME='$INSTANCE_HOME'">>$INSTANCE_HOME/mkebsboot.sh
echo "export LOG_DIR='$LOG_DIR'">>$INSTANCE_HOME/mkebsboot.sh
echo 'cd $INSTANCE_HOME'>>$INSTANCE_HOME/mkebsboot.sh
echo 'find /'>>$INSTANCE_HOME/mkebsboot.sh
echo 'exit 0'>>$INSTANCE_HOME/mkebsboot.sh
# create runscript header
cat > $INSTANCE_HOME/mkebsboot.sh <<END_OF_SCRIPT
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
PROMPT_COMMAND='echo -ne "\033]0;mkebsboot\007"'
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
export INSTANCE_NAME='mkebsboot'
export TMP_DIR='$TMP_DIR'
export INSTANCE_NAME='$INSTANCE_NAME'
export INSTANCE_HOME='$INSTANCE_HOME'
export LOG_DIR='$LOG_DIR'
END_OF_SCRIPT
# add desired commands from the user
cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT'
cd $INSTANCE_HOME
find /
END_OF_SCRIPT
# add runscript footer
cat >> $INSTANCE_HOME/mkebsboot.sh <<'END_OF_SCRIPT'
exit 0
END_OF_SCRIPT
chmod u+x $INSTANCE_HOME/mkebsboot.sh
;;
status)
@ -95,12 +107,15 @@ start)
;;
tail)
default || exit 1
tail $LOG_DIR/stdout.log;;
tail $LOG_DIR/stdout.log
;;
tailerr)
default || exit 1
tail $LOG_DIR/stderr.log;;
tail $LOG_DIR/stderr.log
;;
run)
default || exit 1
$INSTANCE_HOME/$INSTANCE_NAME.sh;;
$INSTANCE_HOME/$INSTANCE_NAME.sh
;;
esac
exit 0

View File

@ -1,15 +1,27 @@
mkdir -p /tmp/$USER/scripttest
rm /tmp/$USER/scripttest/yahooprod.sh 2>&-
echo '#!/bin/bash'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'set +u'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'shopt -s xpg_echo'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'shopt -s expand_aliases'>>/tmp/$USER/scripttest/yahooprod.sh
echo "PROMPT_COMMAND='echo -ne \"\033]0;yahooprod\007\"'">>/tmp/$USER/scripttest/yahooprod.sh
echo 'export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin'>>/tmp/$USER/scripttest/yahooprod.sh
echo "export INSTANCE_NAME='yahooprod'">>/tmp/$USER/scripttest/yahooprod.sh
echo "export JAVA_HOME='$JAVA_HOME'">>/tmp/$USER/scripttest/yahooprod.sh
echo 'cd /tmp/$USER/scripttest'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'echo hello'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main'>>/tmp/$USER/scripttest/yahooprod.sh
echo 'exit 0'>>/tmp/$USER/scripttest/yahooprod.sh
# create runscript header
cat > /tmp/$USER/scripttest/yahooprod.sh <<END_OF_SCRIPT
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
PROMPT_COMMAND='echo -ne "\033]0;yahooprod\007"'
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
export INSTANCE_NAME='yahooprod'
export JAVA_HOME='$JAVA_HOME'
END_OF_SCRIPT
# add desired commands from the user
cat >> /tmp/$USER/scripttest/yahooprod.sh <<'END_OF_SCRIPT'
cd /tmp/$USER/scripttest
echo hello
echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main
END_OF_SCRIPT
# add runscript footer
cat >> /tmp/$USER/scripttest/yahooprod.sh <<'END_OF_SCRIPT'
exit 0
END_OF_SCRIPT
chmod u+x /tmp/$USER/scripttest/yahooprod.sh

View File

@ -0,0 +1,33 @@
mkdir -p /tmp/$USER/scripttest
# create runscript header
(
cat <<END_OF_SCRIPT
#!/bin/bash
set +u
shopt -s xpg_echo
shopt -s expand_aliases
PROMPT_COMMAND='echo -ne "\033]0;yahooprod\007"'
export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
export INSTANCE_NAME='yahooprod'
export JAVA_HOME='$JAVA_HOME'
END_OF_SCRIPT
) > /tmp/$USER/scripttest/yahooprod.sh
# add desired commands from the user
(
cat <<'END_OF_SCRIPT'
cd /tmp/$USER/scripttest
echo hello
echo $JAVA_HOME/bin/java -DinstanceName=$INSTANCE_NAME myServer.Main
END_OF_SCRIPT
) >> /tmp/$USER/scripttest/yahooprod.sh
# add runscript footer
(
cat <<'END_OF_SCRIPT'
exit 0
END_OF_SCRIPT
) >> /tmp/$USER/scripttest/yahooprod.sh
chmod u+x /tmp/$USER/scripttest/yahooprod.sh