Additional tests and improvements.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/60178809 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/60178809 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/60178809 Branch: refs/heads/master Commit: 60178809b3c51a429e6871bb68404245baa86269 Parents: 89d6926 Author: Geoff Macartney <[email protected]> Authored: Tue Nov 17 16:23:23 2015 +0000 Committer: Geoff Macartney <[email protected]> Committed: Wed Nov 18 01:12:24 2015 +0000 ---------------------------------------------------------------------- .../test/framework/SimpleShellCommand.java | 2 +- .../test/framework/SimpleShellCommandImpl.java | 106 ++++++++------- .../framework/SimpleShellCommandTestImpl.java | 3 +- .../SimpleShellCommandIntegrationTest.java | 133 +++++++++++++------ 4 files changed, 152 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60178809/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java index 1f430a7..fc182ef 100644 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java +++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java @@ -71,5 +71,5 @@ public interface SimpleShellCommand extends Entity, Startable { * The working directory that the script will be run from on the target machine. */ @SetFromFlag("runDir") - ConfigKey<String> RUN_DIR = newConfigKey("run.dir", "directory where downloaded scripts should be put", TMP_DEFAULT); + ConfigKey<String> RUN_DIR = newConfigKey(String.class, "run.dir", "directory where downloaded scripts should be run from"); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60178809/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java index 1ccce5e..c63e1fc 100644 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java +++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java @@ -42,10 +42,7 @@ import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URL; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Random; +import java.util.*; import static org.apache.brooklyn.core.entity.lifecycle.Lifecycle.*; import static org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.setExpectedState; @@ -61,7 +58,6 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel private static final int A_LINE = 80; public static final String DEFAULT_NAME = "download.sh"; private static final String CD = "cd"; - private static final String SHELL_AND = "&&"; @Override public void init() { @@ -69,6 +65,25 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel getLifecycleEffectorTasks().attachLifecycleEffectors(this); } + @Override + public void start(Collection<? extends Location> locations) { + addLocations(filterLocations(locations)); + setExpectedState(this, STARTING); + } + + + @Override + public void stop() { + LOG.debug("{} Stopping simple command", this); + setUpAndRunState(false, STOPPED); + } + + @Override + public void restart() { + LOG.debug("{} Restarting simple command", this); + setUpAndRunState(true, RUNNING); + } + protected SimpleShellCommandLifecycleEffectorTasks getLifecycleEffectorTasks() { return new SimpleShellCommandLifecycleEffectorTasks(); } @@ -78,7 +93,7 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel */ protected void handle(SimpleShellCommand.Result result) { LOG.debug("{}, Result is {}\nwith output [\n{}\n] and error [\n{}\n]", new Object[] { - this, result.getExitCode(), shorten(result.getStdout()), shorten(result.getStderr()) + this, result.getExitCode(), shorten(result.getStdout()), shorten(result.getStderr()) }); } @@ -93,25 +108,6 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel return locations; } - - @Override - public void start(Collection<? extends Location> locations) { - addLocations(locations); - setExpectedState(this, STARTING); - } - - @Override - public void stop() { - LOG.debug("{} Stopping simple command", this); - setUpAndRunState(false, STOPPED); - } - - @Override - public void restart() { - LOG.debug("{} Restarting simple command", this); - setUpAndRunState(true, RUNNING); - } - private void setUpAndRunState(boolean up, Lifecycle status) { sensors().set(SERVICE_UP, up); setExpectedState(this, status); @@ -136,31 +132,23 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel String downloadName = DOWNLOAD_URL.getName(); String commandName = COMMAND.getName(); - if (isNonBlank(downloadUrl) && isNonBlank(command)) { - throw illegal("Cannot specify both", downloadName, "and", commandName); - } - - if (isBlank(downloadUrl) && isBlank(commandName)) { - throw illegal("No", downloadName, "and no", commandName, "provided"); + if (!(isNonBlank(downloadUrl) ^ isNonBlank(command))) { + throw illegal("Must specify exactly one of", downloadName, "and", commandName); } - if (Strings.isNonBlank(downloadUrl)) { + if (isNonBlank(downloadUrl)) { String scriptDir = getConfig(SCRIPT_DIR); String scriptPath = calculateDestPath(downloadUrl, scriptDir); result = executeDownloadedScript(machineLocation, downloadUrl, scriptPath); } - if (Strings.isNonBlank(command)) { + if (isNonBlank(command)) { result = executeShellCommand(machineLocation, command); } handle(result); } - private IllegalArgumentException illegal(String ...messages) { - return new IllegalArgumentException(Joiner.on(' ').join(this.toString() + ":", messages)); - } - private SimpleShellCommand.Result executeDownloadedScript(MachineLocation machineLocation, String url, String scriptPath) { SshMachineLocation machine = getSshMachine(ImmutableList.<Location>of(machineLocation)); @@ -169,47 +157,67 @@ public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShel DynamicTasks.queue(install); DynamicTasks.waitForLast(); - machine.execCommands("make the script executable", ImmutableList.<String>of("chmod u+x " + scriptPath)); + List<String> commands = new ArrayList<>(); + commands.add("chmod u+x " + scriptPath); + maybeCdToRunDir(commands); + commands.add(scriptPath); - String runDir = getConfig(RUN_DIR); - String cdAndRun = Joiner.on(' ').join(CD, runDir, SHELL_AND, scriptPath); - - return executeShellCommand(machineLocation, cdAndRun); + return runCommands(machine, commands); } - private SimpleShellCommand.Result executeShellCommand(MachineLocation machineLocation, String command) { SshMachineLocation machine = getSshMachine(ImmutableList.of(machineLocation)); - SshEffectorTasks.SshEffectorTaskFactory<Integer> etf = SshEffectorTasks.ssh(machine, command); - LOG.debug("{} Creating task to execute '{}' on location {}", new Object[] {this, command, machine}); + List<String> commands = new ArrayList<>(); + maybeCdToRunDir(commands); + commands.add(command); + + return runCommands(machine, commands); + } + + private void maybeCdToRunDir(List<String> commands) { + String runDir = getConfig(RUN_DIR); + if (!isBlank(runDir)) { + commands.add(CD + " " + runDir); + } + } + + private Result runCommands(SshMachineLocation machine, List<String> commands) { + SshEffectorTasks.SshEffectorTaskFactory<Integer> etf = SshEffectorTasks.ssh(machine, commands.toArray(new String[]{})); + ProcessTaskWrapper<Integer> job = DynamicTasks.queue(etf); DynamicTasks.waitForLast(); return buildResult(job); } - private <T> SimpleShellCommand.Result buildResult(final ProcessTaskWrapper<Integer> job) { + final int exitCode = job.get(); + final String stdout = job.getStdout().trim(); + final String stderr = job.getStderr().trim(); return new SimpleShellCommand.Result() { @Override public int getExitCode() { - return job.get(); + return exitCode; } @Override public String getStdout() { - return job.getStdout().trim(); + return stdout; } @Override public String getStderr() { - return job.getStderr().trim(); + return stderr; } }; } + private IllegalArgumentException illegal(String message, String ...messages) { + return new IllegalArgumentException(Joiner.on(' ').join(this.toString() + ":", message, messages)); + } + private SshMachineLocation getSshMachine(Collection<? extends Location> hostLocations) { Maybe<SshMachineLocation> host = Locations.findUniqueSshMachineLocation(hostLocations); if (host.isAbsent()) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60178809/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java index 9c9a15a..6a35e73 100644 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java +++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java @@ -47,7 +47,8 @@ public class SimpleShellCommandTestImpl extends SimpleShellCommandImpl implement */ public Collection<? extends Location> filterLocations(Collection<? extends Location> locations) { Entity target = resolveTarget(); - return target.getLocations(); + Collection<Location> targetLocations = target.getLocations(); + return targetLocations; } @Override http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60178809/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java index 7b6c732..7f8f078 100644 --- a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java +++ b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java @@ -27,16 +27,17 @@ import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; import org.apache.brooklyn.core.test.entity.TestEntity; import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.test.Asserts; import org.apache.brooklyn.util.exceptions.Exceptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Random; -import java.util.UUID; import static org.apache.brooklyn.test.framework.BaseTest.TARGET_ENTITY; import static org.apache.brooklyn.test.framework.SimpleShellCommand.COMMAND; @@ -44,7 +45,6 @@ import static org.apache.brooklyn.test.framework.SimpleShellCommandTest.*; import static org.assertj.core.api.Assertions.assertThat; public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSupport { - private static final Logger LOG = LoggerFactory.getLogger(SimpleShellCommandIntegrationTest.class); private static final String UP = "up"; private LocalhostMachineProvisioningLocation localhost; @@ -55,6 +55,48 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); } + @DataProvider(name = "shouldInsistOnJustOneOfCommandAndScript") + public Object[][] createData1() { + + return new Object[][] { + { "pwd", "pwd.sh", Boolean.FALSE }, + { null, null, Boolean.FALSE }, + { "pwd", null, Boolean.TRUE }, + { null, "pwd.sh", Boolean.TRUE } + }; + } + + @Test(dataProvider = "shouldInsistOnJustOneOfCommandAndScript") + public void shouldInsistOnJustOneOfCommandAndScript(String command, String script, boolean valid) throws Exception{ + Path scriptPath = null; + String scriptUrl = null; + if (null != script) { + scriptPath = createTempScript("pwd", "pwd"); + scriptUrl = "file:" + scriptPath; + } + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + + app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) + .configure(TARGET_ENTITY, testEntity) + .configure(COMMAND, command) + .configure(DOWNLOAD_URL, scriptUrl)); + + try { + app.start(ImmutableList.of(localhost)); + if (!valid) { + Asserts.shouldHaveFailedPreviously(); + } + + } catch (Exception e) { + Asserts.expectedFailureContains(e, "Must specify exactly one of download.url and command"); + + } finally { + if (null != scriptPath) { + Files.delete(scriptPath); + } + } + } + @Test(groups = "Integration") public void shouldInvokeCommand() { TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); @@ -95,67 +137,76 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor } @Test(groups = "Integration") - public void shouldInvokeScript() { + public void shouldInvokeScript() throws Exception { TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); String text = "hello world"; - String testUrl = createTempScript("script.sh", "echo " + text); + Path testScript = createTempScript("script", "echo " + text); - SimpleShellCommandTest uptime = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) - .configure(TARGET_ENTITY, testEntity) - .configure(DOWNLOAD_URL, testUrl) - .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) - .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, text))); + try { + SimpleShellCommandTest uptime = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) + .configure(TARGET_ENTITY, testEntity) + .configure(DOWNLOAD_URL, "file:" + testScript) + .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) + .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, text))); - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(localhost)); - assertThat(uptime.sensors().get(SERVICE_UP)).isTrue() - .withFailMessage("Service should be up"); - assertThat(ServiceStateLogic.getExpectedState(uptime)).isEqualTo(Lifecycle.RUNNING) - .withFailMessage("Service should be marked running"); + assertThat(uptime.sensors().get(SERVICE_UP)).isTrue() + .withFailMessage("Service should be up"); + assertThat(ServiceStateLogic.getExpectedState(uptime)).isEqualTo(Lifecycle.RUNNING) + .withFailMessage("Service should be marked running"); + + } finally { + Files.delete(testScript); + } } @Test - public void shouldExecuteInTheRightPlace() throws Exception { + public void shouldExecuteInTheRunDir() throws Exception { TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - String remoteTmp = randomName(); - SimpleShellCommandTest uptime = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) - .configure(TARGET_ENTITY, testEntity) - .configure(COMMAND, "mkdir " + remoteTmp) - .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0))); + Path pwdPath = createTempScript("pwd", "pwd"); - String pwdUrl = createTempScript("pwd.sh", "pwd"); + try { + SimpleShellCommandTest pwd = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) + .configure(TARGET_ENTITY, testEntity) + .configure(DOWNLOAD_URL, "file:" + pwdPath) + .configure(RUN_DIR, "/tmp") + .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) + .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, "/tmp"))); - SimpleShellCommandTest pwd = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) - .configure(TARGET_ENTITY, testEntity) - .configure(DOWNLOAD_URL, pwdUrl) - .configure(RUN_DIR, remoteTmp) - .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) - .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, remoteTmp))); - app.start(ImmutableList.of(localhost)); + SimpleShellCommandTest alsoPwd = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) + .configure(TARGET_ENTITY, testEntity) + .configure(COMMAND, "pwd") + .configure(RUN_DIR, "/tmp") + .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) + .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, "/tmp"))); - assertThat(uptime.sensors().get(SERVICE_UP)).isTrue() - .withFailMessage("Service should be up"); - assertThat(ServiceStateLogic.getExpectedState(uptime)).isEqualTo(Lifecycle.RUNNING) - .withFailMessage("Service should be marked running"); + app.start(ImmutableList.of(localhost)); + + assertThat(pwd.sensors().get(SERVICE_UP)).isTrue().withFailMessage("Service should be up"); + assertThat(ServiceStateLogic.getExpectedState(pwd)).isEqualTo(Lifecycle.RUNNING) + .withFailMessage("Service should be marked running"); + + assertThat(alsoPwd.sensors().get(SERVICE_UP)).isTrue().withFailMessage("Service should be up"); + assertThat(ServiceStateLogic.getExpectedState(alsoPwd)).isEqualTo(Lifecycle.RUNNING) + .withFailMessage("Service should be marked running"); + + } finally { + Files.delete(pwdPath); + } } - private String createTempScript(String filename, String contents) { + private Path createTempScript(String filename, String contents) { try { - Path tempDirectory = Files.createTempDirectory(randomName()); - tempDirectory.toFile().deleteOnExit(); - Path tempFile = Files.createFile(tempDirectory.resolve(filename)); + Path tempFile = Files.createTempFile("SimpleShellCommandIntegrationTest-" + filename, ".sh"); Files.write(tempFile, contents.getBytes()); - return "file:" + tempFile.toString(); + return tempFile; } catch (IOException e) { throw Exceptions.propagate(e); } } - private String randomName() { - return Integer.valueOf(new Random(System.currentTimeMillis()).nextInt(100000)).toString(); - } - }
