mirror of https://github.com/apache/jclouds.git
Issue 126: added composite statements
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2358 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
6045cde384
commit
1ffb7d55ab
|
@ -27,6 +27,7 @@ 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 org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.scriptbuilder.domain.ShellToken;
|
import org.jclouds.scriptbuilder.domain.ShellToken;
|
||||||
|
@ -50,10 +51,7 @@ public class ScriptBuilder {
|
||||||
List<Statement> statements = Lists.newArrayList();
|
List<Statement> statements = Lists.newArrayList();
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<String> variableScopes = Lists.newArrayList();
|
Map<String, Map<String, String>> variableScopes = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
Map<String, String> functions = Maps.newHashMap();
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<String> variablesToUnset = Lists.newArrayList("path", "javaHome", "libraryPath");
|
List<String> variablesToUnset = Lists.newArrayList("path", "javaHome", "libraryPath");
|
||||||
|
@ -75,9 +73,8 @@ public class ScriptBuilder {
|
||||||
* Exports a variable inside the script
|
* Exports a variable inside the script
|
||||||
*/
|
*/
|
||||||
public ScriptBuilder addEnvironmentVariableScope(String scopeName, Map<String, String> variables) {
|
public ScriptBuilder addEnvironmentVariableScope(String scopeName, Map<String, String> variables) {
|
||||||
variableScopes.add(checkNotNull(scopeName, "scopeName"));
|
variableScopes
|
||||||
functions.put(scopeName, Utils.writeFunction(scopeName, Utils
|
.put(checkNotNull(scopeName, "scopeName"), checkNotNull(variables, "variables"));
|
||||||
.writeVariableExporters(checkNotNull(variables, "variables"))));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +90,13 @@ public class ScriptBuilder {
|
||||||
* whether to write a cmd or bash script.
|
* whether to write a cmd or bash script.
|
||||||
*/
|
*/
|
||||||
public String build(final OsFamily osFamily) {
|
public String build(final OsFamily osFamily) {
|
||||||
|
Map<String, String> functions = Maps.newLinkedHashMap();
|
||||||
|
functions.put("abort", Utils.writeFunctionFromResource("abort", osFamily));
|
||||||
|
|
||||||
|
for (Entry<String, Map<String, String>> entry : variableScopes.entrySet()) {
|
||||||
|
functions.put(entry.getKey(), 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));
|
||||||
|
@ -107,10 +111,9 @@ public class ScriptBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
})), osFamily));
|
})), osFamily));
|
||||||
resolveFunctionDependencies(osFamily);
|
resolveFunctionDependencies(functions, osFamily);
|
||||||
if (functions.size() > 0) {
|
if (functions.size() > 0) {
|
||||||
builder.append(ShellToken.BEGIN_FUNCTIONS.to(osFamily));
|
builder.append(ShellToken.BEGIN_FUNCTIONS.to(osFamily));
|
||||||
builder.append(Utils.writeFunctionFromResource("abort", osFamily));
|
|
||||||
for (String function : functions.values()) {
|
for (String function : functions.values()) {
|
||||||
builder.append(Utils.replaceTokens(function, tokenValueMap));
|
builder.append(Utils.replaceTokens(function, tokenValueMap));
|
||||||
}
|
}
|
||||||
|
@ -128,7 +131,7 @@ public class ScriptBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void resolveFunctionDependencies(final OsFamily osFamily) {
|
void resolveFunctionDependencies(Map<String, String> functions, final OsFamily osFamily) {
|
||||||
Iterable<String> dependentFunctions = Iterables.concat(Iterables.transform(statements,
|
Iterable<String> dependentFunctions = Iterables.concat(Iterables.transform(statements,
|
||||||
new Function<Statement, Iterable<String>>() {
|
new Function<Statement, Iterable<String>>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,8 +140,8 @@ public class ScriptBuilder {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
List<String> unresolvedFunctions = Lists.newArrayList(dependentFunctions);
|
List<String> unresolvedFunctions = Lists.newArrayList(dependentFunctions);
|
||||||
Iterables.removeAll(unresolvedFunctions, this.functions.keySet());
|
Iterables.removeAll(unresolvedFunctions, functions.keySet());
|
||||||
for (String functionName : dependentFunctions) {
|
for (String functionName : unresolvedFunctions) {
|
||||||
functions.put(functionName, Utils.writeFunctionFromResource(functionName, osFamily));
|
functions.put(functionName, Utils.writeFunctionFromResource(functionName, osFamily));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF 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 com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Statements used in a shell script
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class StatementList implements Statement {
|
||||||
|
|
||||||
|
public final List<Statement> statements;
|
||||||
|
|
||||||
|
public StatementList(Statement... statements) {
|
||||||
|
this.statements = Lists.newArrayList(checkNotNull(statements, "statements"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatementList(Iterable<Statement> statements) {
|
||||||
|
this.statements = Lists.newArrayList(checkNotNull(statements, "statements"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(OsFamily family) {
|
||||||
|
StringBuilder statementsBuilder = new StringBuilder();
|
||||||
|
for (Statement statement : statements) {
|
||||||
|
statementsBuilder.append(statement.render(family));
|
||||||
|
}
|
||||||
|
return statementsBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<String> functionDependecies(OsFamily family) {
|
||||||
|
List<String> functions = Lists.newArrayList();
|
||||||
|
for (Statement statement : statements) {
|
||||||
|
Iterables.addAll(functions, statement.functionDependecies(family));
|
||||||
|
}
|
||||||
|
return functions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,10 @@ import java.util.Map;
|
||||||
public class Statements {
|
public class Statements {
|
||||||
private static final Kill KILL = new Kill();
|
private static final Kill KILL = new Kill();
|
||||||
|
|
||||||
|
public static Statement newStatementList(Statement... statements) {
|
||||||
|
return new StatementList(statements);
|
||||||
|
}
|
||||||
|
|
||||||
public static Statement switchOn(String variable, Map<String, Statement> valueToActions) {
|
public static Statement switchOn(String variable, Map<String, Statement> valueToActions) {
|
||||||
return new Switch(variable, valueToActions);
|
return new Switch(variable, valueToActions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@ public class Switch implements Statement {
|
||||||
OsFamily.UNIX, "esac\n", OsFamily.WINDOWS, ":END_SWITCH\r\n");
|
OsFamily.UNIX, "esac\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 String variable;
|
private final String variable;
|
||||||
|
|
||||||
|
@ -88,7 +88,8 @@ public class Switch implements Statement {
|
||||||
|
|
||||||
for (Entry<String, Statement> entry : valueToActions.entrySet()) {
|
for (Entry<String, Statement> entry : valueToActions.entrySet()) {
|
||||||
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of(
|
switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of(
|
||||||
"value", entry.getKey(), "action", entry.getValue().render(family))));
|
"value", entry.getKey(), "action", entry.getValue().render(family).replaceAll(
|
||||||
|
"^", " "))));
|
||||||
}
|
}
|
||||||
|
|
||||||
switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family));
|
switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family));
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package org.jclouds.scriptbuilder;
|
package org.jclouds.scriptbuilder;
|
||||||
|
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.call;
|
||||||
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;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
|
||||||
import static org.jclouds.scriptbuilder.domain.Statements.switchOn;
|
import static org.jclouds.scriptbuilder.domain.Statements.switchOn;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
@ -27,10 +29,23 @@ import com.google.common.io.Resources;
|
||||||
*/
|
*/
|
||||||
public class ScriptBuilderTest {
|
public class ScriptBuilderTest {
|
||||||
|
|
||||||
ScriptBuilder testScriptBuilder = new ScriptBuilder().addStatement(
|
ScriptBuilder testScriptBuilder = new ScriptBuilder()
|
||||||
switchOn("1", ImmutableMap.of("start", interpret("echo started{lf}"), "stop",
|
.addEnvironmentVariableScope("default", ImmutableMap.of("runtime", "Moo"))
|
||||||
interpret("echo stopped{lf}")))).addEnvironmentVariableScope("default",
|
.addStatement(
|
||||||
ImmutableMap.of("javaHome", "/apps/jdk1.6"));
|
switchOn(
|
||||||
|
"1",
|
||||||
|
ImmutableMap
|
||||||
|
.of(
|
||||||
|
"start",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
interpret("echo start {varl}RUNTIME{varr}{lf}")),
|
||||||
|
"stop",
|
||||||
|
newStatementList(
|
||||||
|
call("default"),
|
||||||
|
interpret("echo stop {varl}RUNTIME{varr}{lf}")),
|
||||||
|
"status",
|
||||||
|
newStatementList(interpret("echo status ... the following should be empty, as we haven't sourced the variable\"{varl}RUNTIME{varr}\"{lf}")))));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildSimpleWindows() throws MalformedURLException, IOException {
|
public void testBuildSimpleWindows() throws MalformedURLException, IOException {
|
||||||
|
@ -94,20 +109,20 @@ public class ScriptBuilderTest {
|
||||||
ScriptBuilder builder = new ScriptBuilder();
|
ScriptBuilder builder = new ScriptBuilder();
|
||||||
assertEquals(builder.statements.size(), 0);
|
assertEquals(builder.statements.size(), 0);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
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.functions, ImmutableMap.of("default",
|
// assertEquals(builder.functions, ImmutableMap.of("default",
|
||||||
"{fncl}default{fncr} {export} JAVA_HOME={vq}/apps/jdk1.6{vq}{lf}{fnce}"));
|
// "{fncl}default{fncr} {export} JAVA_HOME={vq}/apps/jdk1.6{vq}{lf}{fnce}"));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
public void testNoExport() {
|
// public void testNoExport() {
|
||||||
ScriptBuilder builder = new ScriptBuilder();
|
// ScriptBuilder builder = new ScriptBuilder();
|
||||||
assertEquals(builder.functions.size(), 0);
|
// assertEquals(builder.functions.size(), 0);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Test(expectedExceptions = NullPointerException.class)
|
@Test(expectedExceptions = NullPointerException.class)
|
||||||
public void testExportNPE() {
|
public void testExportNPE() {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF 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.jclouds.scriptbuilder.domain.Statements.*;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "scriptbuilder.StatementListTest")
|
||||||
|
public class StatementListTest {
|
||||||
|
Statement statement = newStatementList(call("default"), interpret("echo started{lf}"));
|
||||||
|
|
||||||
|
public void testUNIX() {
|
||||||
|
assertEquals(statement.render(OsFamily.UNIX), "default || return 1\necho started\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWINDOWS() {
|
||||||
|
assertEquals(statement.render(OsFamily.WINDOWS),
|
||||||
|
"call :default\r\nif errorlevel 1 goto abort\r\necho started\r\n");
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,16 +7,23 @@ GOTO FUNCTION_END
|
||||||
echo aborting: %EXCEPTION%
|
echo aborting: %EXCEPTION%
|
||||||
exit /b 1
|
exit /b 1
|
||||||
:default
|
:default
|
||||||
set JAVA_HOME=/apps/jdk1.6
|
set RUNTIME=Moo
|
||||||
exit /b 0
|
exit /b 0
|
||||||
:FUNCTION_END
|
:FUNCTION_END
|
||||||
set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem
|
set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem
|
||||||
goto CASE%1
|
goto CASE%1
|
||||||
:CASE_start
|
:CASE_start
|
||||||
echo started
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
echo start %RUNTIME%
|
||||||
GOTO END_SWITCH
|
GOTO END_SWITCH
|
||||||
:CASE_stop
|
:CASE_stop
|
||||||
echo stopped
|
call :default
|
||||||
|
if errorlevel 1 goto abort
|
||||||
|
echo stop %RUNTIME%
|
||||||
|
GOTO END_SWITCH
|
||||||
|
:CASE_status
|
||||||
|
echo status ... the following should be empty, as we haven't sourced the variable"%RUNTIME%"
|
||||||
GOTO END_SWITCH
|
GOTO END_SWITCH
|
||||||
:END_SWITCH
|
:END_SWITCH
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
|
@ -8,16 +8,21 @@ function abort {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
function default {
|
function default {
|
||||||
export JAVA_HOME="/apps/jdk1.6"
|
export RUNTIME="Moo"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin
|
||||||
case $1 in
|
case $1 in
|
||||||
start)
|
start)
|
||||||
echo started
|
default || exit 1
|
||||||
|
echo start $RUNTIME
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
echo stopped
|
default || exit 1
|
||||||
|
echo stop $RUNTIME
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
echo status ... the following should be empty, as we haven't sourced the variable"$RUNTIME"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
exit 0
|
exit 0
|
||||||
|
|
Loading…
Reference in New Issue