Fix location handling in integration test and remove unnecessary classes.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/b2713ca4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/b2713ca4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/b2713ca4 Branch: refs/heads/master Commit: b2713ca4d7382ff1057531a6ef92a8a038a59d39 Parents: 6017880 Author: Geoff Macartney <[email protected]> Authored: Wed Nov 18 12:59:25 2015 +0000 Committer: Geoff Macartney <[email protected]> Committed: Wed Nov 18 14:35:48 2015 +0000 ---------------------------------------------------------------------- .../test/framework/SimpleShellCommand.java | 75 ------ .../test/framework/SimpleShellCommandImpl.java | 260 ------------------- ...impleShellCommandLifecycleEffectorTasks.java | 57 ---- .../test/framework/SimpleShellCommandTest.java | 31 ++- .../framework/SimpleShellCommandTestImpl.java | 199 ++++++++++++-- .../SimpleShellCommandIntegrationTest.java | 47 ++-- 6 files changed, 236 insertions(+), 433 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b2713ca4/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 deleted file mode 100644 index fc182ef..0000000 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommand.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.apache.brooklyn.test.framework; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.ImplementedBy; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.trait.Startable; -import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; -import org.apache.brooklyn.entity.software.base.SoftwareProcess; -import org.apache.brooklyn.util.core.flags.SetFromFlag; - -import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKey; - -/** - * Entity to invoke on a node a simple command that will immediately succeed or fail. - * - * Invokes the command in the start operation, and declares itself RUNNING. - */ -@ImplementedBy(SimpleShellCommandImpl.class) -public interface SimpleShellCommand extends Entity, Startable { - - String TMP_DEFAULT = "/tmp"; - - /** - * Result of a command invocation. - */ - interface Result { - int getExitCode(); - String getStdout(); - String getStderr(); - - } - - /** - * Supply the command to invoke directly. Cannot be used together with {@link #DOWNLOAD_URL}. - */ - @SetFromFlag(nullable = false) - ConfigKey<String> COMMAND = ConfigKeys.newConfigKey(String.class, "command", "Command to invoke"); - - /** - * Download a script to invoke. Cannot be used together with {@link #COMMAND}. - */ - @SetFromFlag("downloadUrl") - AttributeSensorAndConfigKey<String, String> DOWNLOAD_URL = SoftwareProcess.DOWNLOAD_URL; - - /** - * Where the script will be downloaded on the target machine. - */ - @SetFromFlag("scriptDir") - ConfigKey<String> SCRIPT_DIR = newConfigKey("script.dir", "directory where downloaded scripts should be put", TMP_DEFAULT); - - /** - * The working directory that the script will be run from on the target machine. - */ - @SetFromFlag("runDir") - 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/b2713ca4/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 deleted file mode 100644 index c63e1fc..0000000 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandImpl.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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.apache.brooklyn.test.framework; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.location.MachineLocation; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; -import org.apache.brooklyn.core.entity.AbstractEntity; -import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; -import org.apache.brooklyn.core.location.Locations; -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.util.collections.MutableList; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.ssh.SshTasks; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.*; - -import static org.apache.brooklyn.core.entity.lifecycle.Lifecycle.*; -import static org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.setExpectedState; -import static org.apache.brooklyn.util.text.Strings.isBlank; -import static org.apache.brooklyn.util.text.Strings.isNonBlank; - -/** - * Implementation for {@link SimpleShellCommand}. - */ -public class SimpleShellCommandImpl extends AbstractEntity implements SimpleShellCommand { - - private static final Logger LOG = LoggerFactory.getLogger(SimpleShellCommandImpl.class); - private static final int A_LINE = 80; - public static final String DEFAULT_NAME = "download.sh"; - private static final String CD = "cd"; - - @Override - public void init() { - super.init(); - 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(); - } - - /** - * Gives the opportunity to sub-classes to do additional work based on the result of the command. - */ - 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()) - }); - } - - private String shorten(String text) { - return Strings.maxlenWithEllipsis(text, A_LINE); - } - - /** - * Does nothing in this class but gives sub-classes the opportunity to filter locations according to some criterion. - */ - public Collection<? extends Location> filterLocations(Collection<? extends Location> locations) { - return locations; - } - - private void setUpAndRunState(boolean up, Lifecycle status) { - sensors().set(SERVICE_UP, up); - setExpectedState(this, status); - } - - public void execute(MachineLocation machineLocation) { - try { - executeCommand(machineLocation); - setUpAndRunState(true, RUNNING); - } catch (Exception e) { - setUpAndRunState(false, ON_FIRE); - throw Exceptions.propagate(e); - } - } - - private void executeCommand(MachineLocation machineLocation) { - - SimpleShellCommand.Result result = null; - String downloadUrl = getConfig(DOWNLOAD_URL); - String command = getConfig(COMMAND); - - String downloadName = DOWNLOAD_URL.getName(); - String commandName = COMMAND.getName(); - - if (!(isNonBlank(downloadUrl) ^ isNonBlank(command))) { - throw illegal("Must specify exactly one of", downloadName, "and", commandName); - } - - if (isNonBlank(downloadUrl)) { - String scriptDir = getConfig(SCRIPT_DIR); - String scriptPath = calculateDestPath(downloadUrl, scriptDir); - result = executeDownloadedScript(machineLocation, downloadUrl, scriptPath); - } - - if (isNonBlank(command)) { - result = executeShellCommand(machineLocation, command); - } - - handle(result); - } - - private SimpleShellCommand.Result executeDownloadedScript(MachineLocation machineLocation, String url, String scriptPath) { - - SshMachineLocation machine = getSshMachine(ImmutableList.<Location>of(machineLocation)); - - TaskFactory<?> install = SshTasks.installFromUrl(ImmutableMap.<String, Object>of(), machine, url, scriptPath); - DynamicTasks.queue(install); - DynamicTasks.waitForLast(); - - List<String> commands = new ArrayList<>(); - commands.add("chmod u+x " + scriptPath); - maybeCdToRunDir(commands); - commands.add(scriptPath); - - return runCommands(machine, commands); - } - - private SimpleShellCommand.Result executeShellCommand(MachineLocation machineLocation, String command) { - - SshMachineLocation machine = getSshMachine(ImmutableList.of(machineLocation)); - - 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 exitCode; - } - - @Override - public String getStdout() { - return stdout; - } - - @Override - public String getStderr() { - 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()) { - throw new IllegalArgumentException("No SSH machine found to run command"); - } - return host.get(); - } - - private String calculateDestPath(String url, String directory) { - try { - URL asUrl = new URL(url); - Iterable<String> path = Splitter.on("/").split(asUrl.getPath()); - String scriptName = getLastPartOfPath(path, DEFAULT_NAME); - return Joiner.on("/").join(directory, "test-" + randomDir(), scriptName); - } catch (MalformedURLException e) { - throw illegal("Malformed URL:", url); - } - } - - private String randomDir() { - return Integer.valueOf(new Random(System.currentTimeMillis()).nextInt(100000)).toString(); - } - - private static String getLastPartOfPath(Iterable<String> path, String defaultName) { - MutableList<String> parts = MutableList.copyOf(path); - Collections.reverse(parts); - Iterator<String> it = parts.iterator(); - String scriptName = null; - - // strip any trailing "/" parts of URL - while (isBlank(scriptName) && it.hasNext()) { - scriptName = it.next(); - } - if (isBlank(scriptName)) { - scriptName = defaultName; - } - return scriptName; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b2713ca4/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandLifecycleEffectorTasks.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandLifecycleEffectorTasks.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandLifecycleEffectorTasks.java deleted file mode 100644 index fdccd99..0000000 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandLifecycleEffectorTasks.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.apache.brooklyn.test.framework; - -import com.google.common.base.Supplier; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.location.MachineLocation; -import org.apache.brooklyn.entity.software.base.lifecycle.MachineLifecycleEffectorTasks; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.util.Collection; - -public class SimpleShellCommandLifecycleEffectorTasks extends MachineLifecycleEffectorTasks { - - private static final Logger LOG = LoggerFactory.getLogger(SimpleShellCommandLifecycleEffectorTasks.class); - - protected Location getLocation(@Nullable Collection<? extends Location> locations) { - return super.getLocation(entity().filterLocations(locations)); - } - - - @Override - protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) { - LOG.debug("Performing lifecycle startProcessesAtMachine on simple command"); - MachineLocation machineLocation = machineS.get(); - entity().execute(machineLocation); - return "Started simple command on " + machineLocation; - } - - @Override - protected String stopProcessesAtMachine() { - LOG.debug("No action needed on simple command stopped"); - return "Stopped"; - } - - protected SimpleShellCommandImpl entity() { - return (SimpleShellCommandImpl) super.entity(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b2713ca4/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java ---------------------------------------------------------------------- diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java index 17621d9..0b71f2f 100644 --- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java +++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java @@ -22,15 +22,21 @@ import com.google.common.collect.Maps; import org.apache.brooklyn.api.entity.ImplementedBy; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; +import org.apache.brooklyn.entity.software.base.SoftwareProcess; import org.apache.brooklyn.util.core.flags.SetFromFlag; import java.util.Map; +import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKey; + /** * Tests using a simple command execution. */ @ImplementedBy(SimpleShellCommandTestImpl.class) -public interface SimpleShellCommandTest extends SimpleShellCommand, BaseTest { +public interface SimpleShellCommandTest extends BaseTest { + + String TMP_DEFAULT = "/tmp"; /** * Equals assertion on command result. @@ -53,6 +59,29 @@ public interface SimpleShellCommandTest extends SimpleShellCommand, BaseTest { String IS_EMPTY = "isEmpty"; /** + * Supply the command to invoke directly. Cannot be used together with {@link #DOWNLOAD_URL}. + */ + @SetFromFlag(nullable = false) + ConfigKey<String> COMMAND = ConfigKeys.newConfigKey(String.class, "command", "Command to invoke"); + + /** + * Download a script to invoke. Cannot be used together with {@link #COMMAND}. + */ + @SetFromFlag("downloadUrl") + AttributeSensorAndConfigKey<String, String> DOWNLOAD_URL = SoftwareProcess.DOWNLOAD_URL; + + /** + * Where the script will be downloaded on the target machine. + */ + @SetFromFlag("scriptDir") + ConfigKey<String> SCRIPT_DIR = newConfigKey("script.dir", "directory where downloaded scripts should be put", TMP_DEFAULT); + + /** + * The working directory that the script will be run from on the target machine. + */ + @SetFromFlag("runDir") + ConfigKey<String> RUN_DIR = newConfigKey(String.class, "run.dir", "directory where downloaded scripts should be run from"); + /** * Assertions on the exit code of the simple command. * * If not explicitly configured, the default assertion is a non-zero exit code. http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b2713ca4/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 6a35e73..c0ce8fc 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 @@ -20,39 +20,92 @@ package org.apache.brooklyn.test.framework; import com.google.common.base.Joiner; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; -import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.mgmt.TaskFactory; +import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.location.Machines; +import org.apache.brooklyn.location.ssh.SshMachineLocation; import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.core.task.DynamicTasks; +import org.apache.brooklyn.util.core.task.ssh.SshTasks; +import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.text.Identifiers; +import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import static org.apache.brooklyn.core.entity.lifecycle.Lifecycle.*; +import static org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.setExpectedState; import static org.apache.brooklyn.util.groovy.GroovyJavaMethods.truth; +import static org.apache.brooklyn.util.text.Strings.isBlank; +import static org.apache.brooklyn.util.text.Strings.isNonBlank; import static org.apache.commons.collections.MapUtils.isEmpty; -public class SimpleShellCommandTestImpl extends SimpleShellCommandImpl implements SimpleShellCommandTest { +public class SimpleShellCommandTestImpl extends AbstractTest implements SimpleShellCommandTest { public static final int SUCCESS = 0; + private static final Logger LOG = LoggerFactory.getLogger(SimpleShellCommandTestImpl.class); + private static final int A_LINE = 80; + public static final String DEFAULT_NAME = "download.sh"; + private static final String CD = "cd"; + @Override - public Entity resolveTarget() { - return AbstractTest.resolveTarget(getExecutionContext(), this); + public void start(Collection<? extends Location> locations) { + setExpectedState(this, STARTING); + execute(); } - /** - * The test will choose the location of its target entity. - */ - public Collection<? extends Location> filterLocations(Collection<? extends Location> locations) { - Entity target = resolveTarget(); - Collection<Location> targetLocations = target.getLocations(); - return targetLocations; + @Override + public void stop() { + LOG.debug("{} Stopping simple command", this); + setUpAndRunState(false, STOPPED); } @Override - protected void handle(SimpleShellCommand.Result result) { + public void restart() { + LOG.debug("{} Restarting simple command", this); + execute(); + } + + private void setUpAndRunState(boolean up, Lifecycle status) { + sensors().set(SERVICE_UP, up); + setExpectedState(this, status); + } + + private static class Result { + int exitCode; + String stdout; + String stderr; + public Result(final ProcessTaskWrapper<Integer> job) { + exitCode = job.get(); + stdout = job.getStdout().trim(); + stderr = job.getStderr().trim(); + } + public int getExitCode() { + return exitCode; + } + public String getStdout() { + return stdout; + } + public String getStderr() { + return stderr; + } + } + + protected void handle(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()) + }); AssertionSupport support = new AssertionSupport(); checkAssertions(support, exitCodeAssertions(), "exit code", result.getExitCode()); checkAssertions(support, getConfig(ASSERT_OUT), "stdout", result.getStdout()); @@ -60,6 +113,120 @@ public class SimpleShellCommandTestImpl extends SimpleShellCommandImpl implement support.validate(); } + private String shorten(String text) { + return Strings.maxlenWithEllipsis(text, A_LINE); + } + + public void execute() { + try { + SshMachineLocation machineLocation = + Machines.findUniqueMachineLocation(resolveTarget().getLocations(), SshMachineLocation.class).get(); + executeCommand(machineLocation); + setUpAndRunState(true, RUNNING); + } catch (Throwable t) { + setUpAndRunState(false, ON_FIRE); + throw Exceptions.propagate(t); + } + } + + private void executeCommand(SshMachineLocation machineLocation) { + + Result result = null; + String downloadUrl = getConfig(DOWNLOAD_URL); + String command = getConfig(COMMAND); + + String downloadName = DOWNLOAD_URL.getName(); + String commandName = COMMAND.getName(); + + if (!(isNonBlank(downloadUrl) ^ isNonBlank(command))) { + throw illegal("Must specify exactly one of", downloadName, "and", commandName); + } + + if (isNonBlank(downloadUrl)) { + String scriptDir = getConfig(SCRIPT_DIR); + String scriptPath = calculateDestPath(downloadUrl, scriptDir); + result = executeDownloadedScript(machineLocation, downloadUrl, scriptPath); + } + + if (isNonBlank(command)) { + result = executeShellCommand(machineLocation, command); + } + + handle(result); + } + + private Result executeDownloadedScript(SshMachineLocation machineLocation, String url, String scriptPath) { + + TaskFactory<?> install = SshTasks.installFromUrl(ImmutableMap.<String, Object>of(), machineLocation, url, scriptPath); + DynamicTasks.queue(install); + DynamicTasks.waitForLast(); + + List<String> commands = new ArrayList<>(); + commands.add("chmod u+x " + scriptPath); + maybeCdToRunDir(commands); + commands.add(scriptPath); + + return runCommands(machineLocation, commands); + } + + private Result executeShellCommand(SshMachineLocation machineLocation, String command) { + + List<String> commands = new ArrayList<>(); + maybeCdToRunDir(commands); + commands.add(command); + + return runCommands(machineLocation, 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(commands.toArray(new String[]{})) + .machine(machine); + + ProcessTaskWrapper<Integer> job = DynamicTasks.queue(etf); + job.asTask().blockUntilEnded(); + return new Result(job); + } + + + + private IllegalArgumentException illegal(String message, String ...messages) { + return new IllegalArgumentException(Joiner.on(' ').join(this.toString() + ":", message, messages)); + } + + private String calculateDestPath(String url, String directory) { + try { + URL asUrl = new URL(url); + Iterable<String> path = Splitter.on("/").split(asUrl.getPath()); + String scriptName = getLastPartOfPath(path, DEFAULT_NAME); + return Joiner.on("/").join(directory, "test-" + Identifiers.makeRandomId(8), scriptName); + } catch (MalformedURLException e) { + throw illegal("Malformed URL:", url); + } + } + + private static String getLastPartOfPath(Iterable<String> path, String defaultName) { + MutableList<String> parts = MutableList.copyOf(path); + Collections.reverse(parts); + Iterator<String> it = parts.iterator(); + String scriptName = null; + + // strip any trailing "/" parts of URL + while (isBlank(scriptName) && it.hasNext()) { + scriptName = it.next(); + } + if (isBlank(scriptName)) { + scriptName = defaultName; + } + return scriptName; + } + private <T> void checkAssertions(AssertionSupport support, Map<?, ?> assertions, String target, T actual) { if (null == assertions) { return; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b2713ca4/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 7f8f078..c6b5b87 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 @@ -21,38 +21,37 @@ package org.apache.brooklyn.test.framework; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.LocationSpec; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; 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.location.ssh.SshMachineLocation; 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.BeforeMethod; 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 static org.apache.brooklyn.test.framework.BaseTest.TARGET_ENTITY; -import static org.apache.brooklyn.test.framework.SimpleShellCommand.COMMAND; import static org.apache.brooklyn.test.framework.SimpleShellCommandTest.*; import static org.assertj.core.api.Assertions.assertThat; public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSupport { private static final String UP = "up"; - private LocalhostMachineProvisioningLocation localhost; - - protected void setUpApp() { - super.setUpApp(); - localhost = app.getManagementContext().getLocationManager() - .createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); + private LocalhostMachineProvisioningLocation loc; + private SshMachineLocation machine; + + @BeforeMethod(alwaysRun = true) + public void setUp() throws Exception { + super.setUp(); + loc = app.newLocalhostProvisioningLocation(); + machine = loc.obtain(); } @DataProvider(name = "shouldInsistOnJustOneOfCommandAndScript") @@ -66,15 +65,15 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor }; } - @Test(dataProvider = "shouldInsistOnJustOneOfCommandAndScript") - public void shouldInsistOnJustOneOfCommandAndScript(String command, String script, boolean valid) throws Exception{ + @Test(groups= "Integration", 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)); + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) .configure(TARGET_ENTITY, testEntity) @@ -82,7 +81,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .configure(DOWNLOAD_URL, scriptUrl)); try { - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(loc)); if (!valid) { Asserts.shouldHaveFailedPreviously(); } @@ -99,7 +98,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor @Test(groups = "Integration") public void shouldInvokeCommand() { - TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); SimpleShellCommandTest uptime = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) .configure(TARGET_ENTITY, testEntity) @@ -107,7 +106,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, UP))); - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(loc)); assertThat(uptime.sensors().get(SERVICE_UP)).isTrue() .withFailMessage("Service should be up"); @@ -118,7 +117,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor @Test(groups = "Integration") public void shouldNotBeUpIfAssertionFails() { - TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); SimpleShellCommandTest uptime = app.createAndManageChild(EntitySpec.create(SimpleShellCommandTest.class) .configure(TARGET_ENTITY, testEntity) @@ -126,7 +125,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 1))); try { - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(loc)); } catch (Exception e) { assertThat(e.getCause().getMessage().contains("exit code equals 1")); } @@ -138,7 +137,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor @Test(groups = "Integration") public void shouldInvokeScript() throws Exception { - TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); String text = "hello world"; Path testScript = createTempScript("script", "echo " + text); @@ -150,7 +149,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, text))); - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(loc)); assertThat(uptime.sensors().get(SERVICE_UP)).isTrue() .withFailMessage("Service should be up"); @@ -162,9 +161,9 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor } } - @Test + @Test(groups = "Integration") public void shouldExecuteInTheRunDir() throws Exception { - TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); + TestEntity testEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(machine)); Path pwdPath = createTempScript("pwd", "pwd"); @@ -184,7 +183,7 @@ public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSuppor .configure(ASSERT_STATUS, ImmutableMap.of(EQUALS, 0)) .configure(ASSERT_OUT, ImmutableMap.of(CONTAINS, "/tmp"))); - app.start(ImmutableList.of(localhost)); + app.start(ImmutableList.of(loc)); assertThat(pwd.sensors().get(SERVICE_UP)).isTrue().withFailMessage("Service should be up"); assertThat(ServiceStateLogic.getExpectedState(pwd)).isEqualTo(Lifecycle.RUNNING)
