Testing winrm exit codes
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/10071a92 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/10071a92 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/10071a92 Branch: refs/heads/master Commit: 10071a928c57aa3178442d9f72f22d47798ff7ca Parents: 2995471 Author: Aled Sage <[email protected]> Authored: Mon Sep 21 21:36:11 2015 +0100 Committer: Aled Sage <[email protected]> Committed: Wed Sep 23 01:32:48 2015 +0100 ---------------------------------------------------------------------- ...laWindowsProcessWinrmExitStatusLiveTest.java | 291 ++++++++++ ...nillaWindowsProcessWinrmStreamsLiveTest.java | 80 ++- .../location/WinRmMachineLocationLiveTest.java | 563 ++++++++++++++++++- .../base/test/location/WindowsTestFixture.java | 71 +++ usage/camp/pom.xml | 6 + .../camp/brooklyn/WindowsYamlLiveTest.java | 410 ++++++++++++++ .../apache/brooklyn/camp/brooklyn/echoArg.bat | 19 + .../camp/brooklyn/echoFreemarkerMyarg.bat | 18 + .../camp/brooklyn/echoFreemarkerMyarg.ps1 | 18 + .../apache/brooklyn/camp/brooklyn/echoMyArg.ps1 | 22 + .../org/apache/brooklyn/camp/brooklyn/exit0.bat | 18 + .../org/apache/brooklyn/camp/brooklyn/exit0.ps1 | 18 + .../org/apache/brooklyn/camp/brooklyn/exit1.bat | 18 + .../org/apache/brooklyn/camp/brooklyn/exit1.ps1 | 19 + 14 files changed, 1521 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmExitStatusLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmExitStatusLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmExitStatusLiveTest.java new file mode 100644 index 0000000..998d987 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmExitStatusLiveTest.java @@ -0,0 +1,291 @@ +/* + * 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.entity.software.base; + +import static org.testng.Assert.fail; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.core.entity.Attributes; +import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.entity.factory.ApplicationBuilder; +import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; +import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.entity.software.base.test.location.WindowsTestFixture; +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class VanillaWindowsProcessWinrmExitStatusLiveTest { + private static final Logger LOG = LoggerFactory.getLogger(VanillaWindowsProcessWinrmExitStatusLiveTest.class); + + private static final String INVALID_CMD = "thisCommandDoesNotExistAEFafiee3d"; + + protected ManagementContextInternal mgmt; + protected TestApplication app; + protected MachineProvisioningLocation<WinRmMachineLocation> location; + protected WinRmMachineLocation machine; + + @BeforeClass(alwaysRun=true) + public void setUpClass() throws Exception { + mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault()); + + location = WindowsTestFixture.setUpWindowsLocation(mgmt); + machine = location.obtain(ImmutableMap.of()); + } + + @AfterClass(alwaysRun=true) + public void tearDownClass() throws Exception { + try { + try { + if (location != null) location.release(machine); + } finally { + if (mgmt != null) Entities.destroyAll(mgmt); + } + } catch (Throwable t) { + LOG.error("Caught exception in tearDownClass method", t); + } finally { + mgmt = null; + } + } + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class) + .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true); + app = ApplicationBuilder.newManagedApp(appSpec, mgmt); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + try { + try { + if (app != null) Entities.destroy(app); + } catch (Throwable t) { + LOG.error("Caught exception in tearDown method", t); + } + } finally { + app = null; + } + } + + @Test(groups = "Live") + public void testExecWithZeroExitCodes() { + VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(VanillaWindowsProcess.PRE_INSTALL_COMMAND, "echo preinstall") + .configure(VanillaWindowsProcess.INSTALL_COMMAND, "echo install") + .configure(VanillaWindowsProcess.POST_INSTALL_COMMAND, "echo postinstall") + .configure(VanillaWindowsProcess.CUSTOMIZE_COMMAND, "echo customize") + .configure(VanillaWindowsProcess.PRE_LAUNCH_COMMAND, "echo prelaunch") + .configure(VanillaWindowsProcess.LAUNCH_COMMAND, "echo launch") + .configure(VanillaWindowsProcess.POST_LAUNCH_COMMAND, "echo postlaunch") + .configure(VanillaWindowsProcess.CHECK_RUNNING_COMMAND, "echo checkrunning") + .configure(VanillaWindowsProcess.STOP_COMMAND, "echo stop")); + + app.start(ImmutableList.of(machine)); + LOG.info("app started; asserting up"); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + + entity.stop(); + LOG.info("stopping entity"); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false); + } + + @Test(groups = "Live") + public void testExecPsWithZeroExitCodes() { + VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(VanillaWindowsProcess.PRE_INSTALL_POWERSHELL_COMMAND, "Write-Host preinstall") + .configure(VanillaWindowsProcess.INSTALL_POWERSHELL_COMMAND, "Write-Host install") + .configure(VanillaWindowsProcess.POST_INSTALL_POWERSHELL_COMMAND, "Write-Host postinstall") + .configure(VanillaWindowsProcess.CUSTOMIZE_POWERSHELL_COMMAND, "Write-Host customize") + .configure(VanillaWindowsProcess.PRE_LAUNCH_POWERSHELL_COMMAND, "Write-Host prelaunch") + .configure(VanillaWindowsProcess.LAUNCH_POWERSHELL_COMMAND, "Write-Host launch") + .configure(VanillaWindowsProcess.POST_LAUNCH_POWERSHELL_COMMAND, "Write-Host postlaunch") + .configure(VanillaWindowsProcess.CHECK_RUNNING_POWERSHELL_COMMAND, "Write-Host checkrunning") + .configure(VanillaWindowsProcess.STOP_POWERSHELL_COMMAND, "Write-Host stop")); + + app.start(ImmutableList.of(machine)); + LOG.info("app started; asserting up"); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + + entity.stop(); + LOG.info("stopping entity"); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false); + } + + @Test(groups = "Live") + public void testPreInstallNonZeroExitCode() { + runExecNonZeroExitCode("pre-install-command"); + } + + @Test(groups = "Live") + public void testInstallNonZeroExitCode() { + runExecNonZeroExitCode("install-command"); + } + + @Test(groups = "Live") + public void testPostInstallNonZeroExitCode() { + runExecNonZeroExitCode("post-install-command"); + } + + @Test(groups = "Live") + public void testCustomizeNonZeroExitCode() { + runExecNonZeroExitCode("customize-command"); + } + + @Test(groups = "Live") + public void testPreLaunchNonZeroExitCode() { + runExecNonZeroExitCode("pre-launch-command"); + } + + @Test(groups = "Live") + public void testLaunchNonZeroExitCode() { + runExecNonZeroExitCode("launch-command"); + } + + @Test(groups = "Live") + public void testCheckRunningNonZeroExitCode() { + runExecNonZeroExitCode("is-running-command"); + } + + @Test(groups = "Live") + public void testStopNonZeroExitCode() { + runExecNonZeroExitCode("stop-command"); + } + + @Test(groups = "Live") + public void testPsPreInstallNonZeroExitCode() { + runExecPsNonZeroExitCode("pre-install-command"); + } + + @Test(groups = "Live") + public void testPsInstallNonZeroExitCode() { + runExecPsNonZeroExitCode("install-command"); + } + + @Test(groups = "Live") + public void testPsPostInstallNonZeroExitCode() { + runExecPsNonZeroExitCode("post-install-command"); + } + + @Test(groups = "Live") + public void testPsCustomizeNonZeroExitCode() { + runExecPsNonZeroExitCode("customize-command"); + } + + @Test(groups = "Live") + public void testPsPreLaunchNonZeroExitCode() { + runExecPsNonZeroExitCode("pre-launch-command"); + } + + @Test(groups = "Live") + public void testPsLaunchNonZeroExitCode() { + runExecPsNonZeroExitCode("launch-command"); + } + + @Test(groups = "Live") + public void testPsCheckRunningNonZeroExitCode() { + runExecPsNonZeroExitCode("is-running-command"); + } + + @Test(groups = "Live") + public void testPsStopNonZeroExitCode() { + runExecPsNonZeroExitCode("stop-command"); + } + + protected void runExecNonZeroExitCode(String phase) { + VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(VanillaWindowsProcess.PRE_INSTALL_COMMAND, phase.equals("pre-install-command") ? INVALID_CMD : "echo install") + .configure(VanillaWindowsProcess.INSTALL_COMMAND, phase.equals("install-command") ? INVALID_CMD : "echo install") + .configure(VanillaWindowsProcess.POST_INSTALL_COMMAND, phase.equals("post-install-command") ? INVALID_CMD : "echo postinstall") + .configure(VanillaWindowsProcess.CUSTOMIZE_COMMAND, phase.equals("customize-command") ? INVALID_CMD : "echo customize") + .configure(VanillaWindowsProcess.PRE_LAUNCH_COMMAND, phase.equals("pre-launch-command") ? INVALID_CMD : "echo prelaunch") + .configure(VanillaWindowsProcess.LAUNCH_COMMAND, phase.equals("launch-command") ? INVALID_CMD : "echo launch") + .configure(VanillaWindowsProcess.POST_LAUNCH_COMMAND, phase.equals("post-launch-command") ? INVALID_CMD : "echo postlaunch") + .configure(VanillaWindowsProcess.CHECK_RUNNING_COMMAND, phase.equals("is-running-command") ? INVALID_CMD : "echo checkrunning") + .configure(VanillaWindowsProcess.STOP_COMMAND, phase.equals("stop-command") ? INVALID_CMD : "echo stop") + .configure(BrooklynConfigKeys.START_TIMEOUT, Duration.ONE_MINUTE)); + + if (phase.equals("stop-command")) { + app.start(ImmutableList.of(machine)); + try { + entity.stop(); + fail(); + } catch (Exception e) { + if (!(e.toString().contains("invalid result") && e.toString().contains("for "+phase))) throw e; + } + } else { + try { + app.start(ImmutableList.of(machine)); + fail(); + } catch (Exception e) { + if (!(e.toString().contains("invalid result") && e.toString().contains("for "+phase))) throw e; + } + } + } + + protected void runExecPsNonZeroExitCode(String phase) { + VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(VanillaWindowsProcess.PRE_INSTALL_POWERSHELL_COMMAND, phase.equals("pre-install-command") ? INVALID_CMD : "Write-Host install") + .configure(VanillaWindowsProcess.INSTALL_POWERSHELL_COMMAND, phase.equals("install-command") ? INVALID_CMD : "Write-Host install") + .configure(VanillaWindowsProcess.POST_INSTALL_POWERSHELL_COMMAND, phase.equals("post-install-command") ? INVALID_CMD : "Write-Host postinstall") + .configure(VanillaWindowsProcess.CUSTOMIZE_POWERSHELL_COMMAND, phase.equals("customize-command") ? INVALID_CMD : "Write-Host customize") + .configure(VanillaWindowsProcess.PRE_LAUNCH_POWERSHELL_COMMAND, phase.equals("pre-launch-command") ? INVALID_CMD : "Write-Host prelaunch") + .configure(VanillaWindowsProcess.LAUNCH_POWERSHELL_COMMAND, phase.equals("launch-command") ? INVALID_CMD : "Write-Host launch") + .configure(VanillaWindowsProcess.POST_LAUNCH_POWERSHELL_COMMAND, phase.equals("post-launch-command") ? INVALID_CMD : "Write-Host postlaunch") + .configure(VanillaWindowsProcess.CHECK_RUNNING_POWERSHELL_COMMAND, phase.equals("is-running-command") ? INVALID_CMD : "Write-Host checkrunning") + .configure(VanillaWindowsProcess.STOP_POWERSHELL_COMMAND, phase.equals("stop-command") ? INVALID_CMD : "Write-Host stop") + .configure(BrooklynConfigKeys.START_TIMEOUT, Duration.ONE_MINUTE)); + + if (phase.equals("stop-command")) { + app.start(ImmutableList.of(machine)); + try { + entity.stop(); + fail(); + } catch (Exception e) { + if (!(e.toString().contains("invalid result") && e.toString().contains("for "+phase))) throw e; + } + } else { + try { + app.start(ImmutableList.of(machine)); + fail(); + } catch (Exception e) { + if (!(e.toString().contains("invalid result") && e.toString().contains("for "+phase))) throw e; + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmStreamsLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmStreamsLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmStreamsLiveTest.java index 2ee310b..fdc4c59 100644 --- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmStreamsLiveTest.java +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaWindowsProcessWinrmStreamsLiveTest.java @@ -18,41 +18,78 @@ */ package org.apache.brooklyn.entity.software.base; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import java.util.Map; + import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.entity.factory.ApplicationBuilder; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.entity.software.base.test.location.WindowsTestFixture; +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.util.Map; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; public class VanillaWindowsProcessWinrmStreamsLiveTest extends AbstractSoftwareProcessStreamsTest { - private Location location; + + private static final Logger LOG = LoggerFactory.getLogger(VanillaWindowsProcessWinrmStreamsLiveTest.class); + + protected MachineProvisioningLocation<WinRmMachineLocation> location; + protected WinRmMachineLocation machine; + + // Using BeforeClass so that uses just a single VM for all tests + @BeforeClass(alwaysRun = true) + public void setUpClass() throws Exception { + super.setUp(); + if (app != null) Entities.destroy(app); + + location = WindowsTestFixture.setUpWindowsLocation(mgmt); + machine = location.obtain(ImmutableMap.of()); + } + + @AfterClass(alwaysRun = true) + public void tearDownClass() throws Exception { + try { + if (location != null && machine != null) location.release(machine); + } catch (Throwable t) { + LOG.error("Caught exception in tearDownClass method", t); + } finally { + super.tearDown(); + } + } - @BeforeMethod(alwaysRun=true) + @BeforeMethod(alwaysRun = true) @Override public void setUp() throws Exception { - super.setUp(); + app = ApplicationBuilder.newManagedApp(TestApplication.class, mgmt); + } - Map<String, Object> config = ImmutableMap.<String, Object>builder() - .put("inboundPorts", ImmutableList.of(5985, 3389)) - .put("osFamily", "windows") - .put("displayName", "AWS Oregon (Windows)") - .put("imageOwner", "801119661308") - .put("imageNameRegex", "Windows_Server-2012-R2_RTM-English-64Bit-Base-.*") - .put("hardwareId", "m3.medium") - .put("checkRunning.command", "echo true") - .put("useJcloudsSshInit", false) - .build(); - location = ((JcloudsLocation)mgmt.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-1", config)).obtain(); + @AfterMethod(alwaysRun = true) + @Override + public void tearDown() throws Exception { + try { + if (app != null) Entities.destroy(app); + } catch (Throwable t) { + LOG.error("Caught exception in tearDown method", t); + } finally { + app = null; + } } @Test(groups = "Live") @Override public void testGetsStreams() { VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true) .configure(VanillaSoftwareProcess.PRE_INSTALL_COMMAND, "echo " + getCommands().get("winrm: pre-install-command.*")) .configure(VanillaSoftwareProcess.INSTALL_COMMAND, "echo " + getCommands().get("winrm: install.*")) .configure(VanillaSoftwareProcess.POST_INSTALL_COMMAND, "echo " + getCommands().get("winrm: post-install-command.*")) @@ -61,13 +98,14 @@ public class VanillaWindowsProcessWinrmStreamsLiveTest extends AbstractSoftwareP .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, "echo " + getCommands().get("winrm: launch.*")) .configure(VanillaSoftwareProcess.POST_LAUNCH_COMMAND, "echo " + getCommands().get("winrm: post-launch-command.*")) .configure(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND, "echo true")); - app.start(ImmutableList.of(location)); + app.start(ImmutableList.of(machine)); assertStreams(entity); } @Test(groups = "Live") public void testGetsStreamsPowerShell() { VanillaWindowsProcess entity = app.createAndManageChild(EntitySpec.create(VanillaWindowsProcess.class) + .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true) .configure(VanillaWindowsProcess.PRE_INSTALL_POWERSHELL_COMMAND, "echo " + getCommands().get("winrm: pre-install-command.*")) .configure(VanillaWindowsProcess.INSTALL_POWERSHELL_COMMAND, "echo " + getCommands().get("winrm: install.*")) .configure(VanillaWindowsProcess.POST_INSTALL_POWERSHELL_COMMAND, "echo " + getCommands().get("winrm: post-install-command.*")) @@ -76,7 +114,7 @@ public class VanillaWindowsProcessWinrmStreamsLiveTest extends AbstractSoftwareP .configure(VanillaWindowsProcess.LAUNCH_POWERSHELL_COMMAND, "echo " + getCommands().get("winrm: launch.*")) .configure(VanillaWindowsProcess.POST_LAUNCH_POWERSHELL_COMMAND, "echo " + getCommands().get("winrm: post-launch-command.*")) .configure(VanillaWindowsProcess.CHECK_RUNNING_POWERSHELL_COMMAND, "echo true")); - app.start(ImmutableList.of(location)); + app.start(ImmutableList.of(machine)); assertStreams(entity); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java index dd4dee7..615eda7 100644 --- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WinRmMachineLocationLiveTest.java @@ -19,76 +19,581 @@ package org.apache.brooklyn.entity.software.base.test.location; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.brooklyn.api.location.MachineProvisioningLocation; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; import org.apache.brooklyn.core.test.entity.TestApplication; -import org.apache.brooklyn.location.jclouds.JcloudsLocation; - -import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; - +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; +import org.apache.brooklyn.util.text.Identifiers; +import org.apache.brooklyn.util.time.Time; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.apache.brooklyn.location.jclouds.JcloudsWinRmMachineLocation; +import com.google.api.client.util.Charsets; +import com.google.common.base.Joiner; +import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.io.Files; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; +/** + * Tests execution of commands (batch and powershell) on Windows over WinRM, and of + * file upload. + * + * There are limitations with what is supported by PyWinRM. These are highlighted in + * tests marked as "WIP" (see individual tests). + * + * These limitations are documented in docs/guide/yaml/winrm/index.md. + * Please update the docs if you encountered new situations, or change the behaviuor + * of existing use-cases. + */ public class WinRmMachineLocationLiveTest { - - // FIXME failing locally with: - // Caused by: Traceback (most recent call last): - // File "__pyclasspath__/winrm/__init__.py", line 40, in run_cmd - // File "__pyclasspath__/winrm/protocol.py", line 118, in open_shell - // File "__pyclasspath__/winrm/protocol.py", line 190, in send_message - // File "__pyclasspath__/winrm/transport.py", line 112, in send_message - // winrm.exceptions.WinRMTransportError: 500 WinRMTransport. [Errno 20001] getaddrinfo failed - // at org.python.core.PyException.doRaise(PyException.java:226) + private static final int MAX_EXECUTOR_THREADS = 100; + + /* + * TODO: Deferred implementing copyFrom or environment variables. + */ + private static final Logger LOG = LoggerFactory.getLogger(BrooklynAppLiveTestSupport.class); - protected JcloudsLocation loc; + private static final String INVALID_CMD = "thisCommandDoesNotExistAEFafiee3d"; + private static final String PS_ERR_ACTION_PREF_EQ_STOP = "$ErrorActionPreference = \"Stop\""; + + protected MachineProvisioningLocation<WinRmMachineLocation> loc; protected TestApplication app; protected ManagementContextInternal mgmt; - private JcloudsWinRmMachineLocation machine; + private WinRmMachineLocation machine; + + private ListeningExecutorService executor; @BeforeClass(alwaysRun=true) public void setUpClass() throws Exception { + executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(MAX_EXECUTOR_THREADS)); + mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault()); - JcloudsLocation loc = (JcloudsLocation) mgmt.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-2", ImmutableMap.<String, Object>builder() - .put("inboundPorts", ImmutableList.of(5985, 3389)) - .put("displayName", "AWS Oregon (Windows)") - .put("imageOwner", "801119661308") - .put("imageNameRegex", "Windows_Server-2012-R2_RTM-English-64Bit-Base-.*") - .put("hardwareId", "m3.medium") - .put("useJcloudsSshInit", false) - .build()); - machine = (JcloudsWinRmMachineLocation) loc.obtain(); + + loc = WindowsTestFixture.setUpWindowsLocation(mgmt); + machine = loc.obtain(ImmutableMap.of()); } - + @AfterClass(alwaysRun=true) public void tearDownClass() throws Exception { try { + if (executor != null) executor.shutdownNow(); if (machine != null) loc.release(machine); if (mgmt != null) Entities.destroyAll(mgmt); } catch (Throwable t) { LOG.error("Caught exception in tearDown method", t); } finally { + executor = null; mgmt = null; } } @Test(groups="Live") + public void testCopyTo() throws Exception { + String contents = "abcdef"; + runCopyTo(contents); + runCopyFileTo(contents); + } + + // Takes several minutes to upload/download! + @Test(groups="Live") + public void testLargeFileCopyTo() throws Exception { + String contents = Identifiers.makeRandomId(65537); + runCopyTo(contents); + runCopyFileTo(contents); + } + + protected void runCopyTo(String contents) throws Exception { + String remotePath = "C:\\myfile-"+Identifiers.makeRandomId(4)+".txt"; + machine.copyTo(new ByteArrayInputStream(contents.getBytes()), remotePath); + + WinRmToolResponse response = machine.executeScript("type "+remotePath); + String msg = "statusCode="+response.getStatusCode()+"; out="+response.getStdOut()+"; err="+response.getStdErr(); + assertEquals(response.getStatusCode(), 0, msg); + assertEquals(response.getStdOut().trim(), contents, msg); + } + + protected void runCopyFileTo(String contents) throws Exception { + File localFile = File.createTempFile("winrmtest"+Identifiers.makeRandomId(4), ".txt"); + try { + Files.write(contents, localFile, Charsets.UTF_8); + String remotePath = "C:\\myfile-"+Identifiers.makeRandomId(4)+".txt"; + machine.copyTo(localFile, remotePath); + + WinRmToolResponse response = machine.executeScript("type "+remotePath); + String msg = "statusCode="+response.getStatusCode()+"; out="+response.getStdOut()+"; err="+response.getStdErr(); + assertEquals(response.getStatusCode(), 0, msg); + assertEquals(response.getStdOut().trim(), contents, msg); + } finally { + localFile.delete(); + } + } + + @Test(groups="Live") public void testExecScript() throws Exception { - WinRmToolResponse response = machine.executeScript("echo true"); - assertEquals(response.getStatusCode(), 0); - assertEquals(response.getStdErr(), ""); + assertExecSucceeds("echo myline", "myline", ""); + } + + /* + * TODO Not supported in PyWinRM. + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_cmd("echo first \r\n echo second") + * gives just "first". + */ + @Test(groups={"Live", "WIP"}) + public void testExecMultiLineScript() throws Exception { + assertExecSucceeds("echo first" + "\r\n" + "echo second", "first"+"\r\n"+"second", ""); + } + + /* + * TODO Not supported in PyWinRM. Under the covers, we just concatenate the commands. + * See {@link #testExecMultiLineScript()}. + */ + @Test(groups={"Live", "WIP"}) + public void testExecMultiPartScript() throws Exception { + assertExecSucceeds(ImmutableList.of("echo first", "echo second"), "first"+"\r\n"+"second", ""); + } + + @Test(groups="Live") + public void testExecFailingScript() throws Exception { + final String INVALID_CMD = "thisCommandDoesNotExistAEFafiee3d"; + + // Single commands + assertExecFails(INVALID_CMD); + assertExecFails(ImmutableList.of(INVALID_CMD)); + } + + @Test(groups="Live") + public void testExecScriptExit0() throws Exception { + assertExecSucceeds("exit /B 0", "", ""); + assertExecSucceeds(ImmutableList.of("exit /B 0"), "", ""); + } + + /* + * TODO Not supported in PyWinRM. + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_cmd("exit /B 1") + * gives exit code 0. + */ + @Test(groups={"Live", "WIP"}) + public void testExecScriptExit1() throws Exception { + // Single commands + assertExecFails("exit /B 1"); + assertExecFails(ImmutableList.of("exit /B 1")); + } + + @Test(groups="Live") + public void testExecBatchFileSingleLine() throws Exception { + String script = "EXIT /B 0"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecSucceeds(scriptPath, null, ""); + } + + @Test(groups="Live") + public void testExecBatchFileMultiLine() throws Exception { + String script = Joiner.on("\n").join( + "@ECHO OFF", + "echo first", + "echo second", + "EXIT /B 0"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecSucceeds(scriptPath, "first"+"\r\n"+"second", ""); + } + + @Test(groups="Live") + public void testExecBatchFileWithArgs() throws Exception { + String script = Joiner.on("\n").join( + "@ECHO OFF", + "echo got %1", + "echo got %2", + "EXIT /B 0"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecSucceeds(scriptPath+" first second", "got first"+"\r\n"+"got second", ""); + } + + @Test(groups="Live") + public void testExecBatchFileWithExit1() throws Exception { + String script = "EXIT /B 1"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecFails(scriptPath); + } + + @Test(groups="Live") + public void testExecCorruptExe() throws Exception { + String exe = "garbage"; + String exePath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".exe"; + machine.copyTo(new ByteArrayInputStream(exe.getBytes()), exePath); + + assertExecFails(exePath); + } + + @Test(groups="Live") + public void testExecFilePs() throws Exception { + String script = Joiner.on("\r\n").join( + "Write-Host myline", + "exit 0"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsSucceeds( + "PowerShell -NonInteractive -NoProfile -Command "+scriptPath, + "myline", + ""); + } + + @Test(groups="Live") + public void testExecFilePsWithExit1() throws Exception { + String script = Joiner.on("\r\n").join( + "Write-Host myline", + "exit 1"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecFails("PowerShell -NonInteractive -NoProfile -Command "+scriptPath); + } + + /* + * TODO Not supported in PyWinRM - single line .ps1 file with "exit 1" gives an + * exit code 0 over PyWinRM, but an exit code 1 when executed locally! + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_cmd("PowerShell -NonInteractive -NoProfile -Command C:\singleLineExit1.ps1") + * gives exit code 0. + */ + @Test(groups={"Live", "WIP"}) + public void testExecFilePsWithSingleLineExit1() throws Exception { + String script = "exit 1"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecFails("PowerShell -NonInteractive -NoProfile -Command "+scriptPath); + } + + @Test(groups="Live") + public void testExecPsScript() throws Exception { + assertExecPsSucceeds("Write-Host myline", "myline", ""); + } + + @Test(groups="Live") + public void testExecPsMultiLineScript() throws Exception { + // Note stdout is "\n" rather than "\r\n" (the latter is returned for run_cmd, versus run_ps) + assertExecPsSucceeds("Write-Host first" + "\r\n" + "Write-Host second", "first"+"\n"+"second", ""); + } + + @Test(groups="Live") + public void testExecPsMultiLineScriptWithoutSlashR() throws Exception { + assertExecPsSucceeds("Write-Host first" + "\n" + "Write-Host second", "first"+"\n"+"second", ""); + } + + @Test(groups="Live") + public void testExecPsMultiPartScript() throws Exception { + assertExecPsSucceeds(ImmutableList.of("Write-Host first", "Write-Host second"), "first"+"\n"+"second", ""); + } + + @Test(groups="Live") + public void testExecPsBatchFile() throws Exception { + String script = "EXIT /B 0"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsSucceeds("& '"+scriptPath+"'", null, ""); + } + + @Test(groups="Live") + public void testExecPsBatchFileExit1() throws Exception { + String script = "EXIT /B 1"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsFails("& '"+scriptPath+"'"); + } + + /* + * TODO Not supported in PyWinRM - gives exit status 1, rather than the 3 from the batch file. + */ + @Test(groups={"Live", "WIP"}) + public void testExecPsBatchFileExit3() throws Exception { + String script = "EXIT /B 3"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".bat"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + WinRmToolResponse response = machine.executePsScript("& '"+scriptPath+"'"); + String msg = "statusCode="+response.getStatusCode()+"; out="+response.getStdOut()+"; err="+response.getStdErr(); + assertEquals(response.getStatusCode(), 3, msg); + } + + @Test(groups="Live") + public void testExecPsCorruptExe() throws Exception { + String exe = "garbage"; + String exePath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".exe"; + machine.copyTo(new ByteArrayInputStream(exe.getBytes()), exePath); + + assertExecPsFails("& '"+exePath+"'"); + } + + @Test(groups="Live") + public void testExecPsFileWithArg() throws Exception { + String script = Joiner.on("\r\n").join( + "Param(", + " [string]$myarg", + ")", + "Write-Host got $myarg", + "exit 0"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsSucceeds("& "+scriptPath+" -myarg myval", "got myval", ""); + } + + @Test(groups="Live") + public void testExecPsFilePs() throws Exception { + String script = Joiner.on("\r\n").join( + "Write-Host myline", + "exit 0"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsSucceeds("& "+scriptPath, "myline", ""); + } + + @Test(groups="Live") + public void testExecPsFilePsWithExit1() throws Exception { + String script = Joiner.on("\r\n").join( + "Write-Host myline", + "exit 1"); + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + System.out.println(scriptPath); + + assertExecPsFails("& "+scriptPath); + } + + /* + * TODO Not supported in PyWinRM - single line .ps1 file with "exit 1" gives an + * exit code 0 over PyWinRM, but an exit code 1 when executed locally! + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_cmd("PowerShell -NonInteractive -NoProfile -Command C:\singleLineExit1.ps1") + * gives exit code 0. + */ + @Test(groups={"Live", "WIP"}) + public void testExecPsFilePsSingleLineWithExit1() throws Exception { + String script = "exit 1"; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsFails("& "+scriptPath); + } + + /* + * TODO Not supported in PyWinRM - single line .ps1 file with "exit 1" gives an + * exit code 0 over PyWinRM, but an exit code 1 when executed locally! + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_cmd("PowerShell -NonInteractive -NoProfile -Command C:\singleLineGarbage.ps1") + * gives exit code 0. + */ + @Test(groups={"Live", "WIP"}) + public void testExecPsFilePsSingleLineWithInvalidCommand() throws Exception { + String script = INVALID_CMD; + String scriptPath = "C:\\myscript-"+Identifiers.makeRandomId(4)+".ps1"; + machine.copyTo(new ByteArrayInputStream(script.getBytes()), scriptPath); + + assertExecPsFails("& "+scriptPath); + } + + @Test(groups="Live") + public void testConfirmUseOfErrorActionPreferenceDoesNotCauseErr() throws Exception { + // Confirm that ErrorActionPreference=Stop does not itself cause a failure, and still get output on success. + assertExecPsSucceeds(ImmutableList.of(PS_ERR_ACTION_PREF_EQ_STOP, "Write-Host myline"), "myline", ""); + } + + /* + * TODO Not supported in PyWinRM + * + * Executing (in python): + * import winrm + * s = winrm.Session('52.12.211.247', auth=('Administrator', 'pa55w0rd')) + * r = s.run_ps("exit 1") + * gives exit code 0. + */ + @Test(groups={"Live", "WIP"}) + public void testExecPsExit1() throws Exception { + // Single commands + assertExecPsFails("exit 1"); + assertExecPsFails(ImmutableList.of("exit 1")); + + // Multi-part + assertExecPsFails(ImmutableList.of(PS_ERR_ACTION_PREF_EQ_STOP, "Write-Host myline", "exit 1")); + + // Multi-line + assertExecPsFails(PS_ERR_ACTION_PREF_EQ_STOP + "\n" + "Write-Host myline" + "\n" + "exit 1"); + } + + @Test(groups="Live") + public void testExecFailingPsScript() throws Exception { + // Single commands + assertExecPsFails(INVALID_CMD); + assertExecPsFails(ImmutableList.of(INVALID_CMD)); + + // Multi-part commands + assertExecPsFails(ImmutableList.of(PS_ERR_ACTION_PREF_EQ_STOP, "Write-Host myline", INVALID_CMD)); + assertExecPsFails(ImmutableList.of(PS_ERR_ACTION_PREF_EQ_STOP, INVALID_CMD, "Write-Host myline")); + } + + @Test(groups={"Live", "Acceptance"}) + public void testExecConcurrently() throws Exception { + final int NUM_RUNS = 10; + final int TIMEOUT_MINS = 30; + final AtomicInteger counter = new AtomicInteger(); + + // Find the test methods that are enabled, and that are not WIP + List<Method> methodsToRun = Lists.newArrayList(); + Method[] allmethods = WinRmMachineLocationLiveTest.class.getMethods(); + for (Method method : allmethods) { + Test annotatn = method.getAnnotation(Test.class); + if (method.getParameterTypes().length != 0) { + continue; + } + if (method.getName().equals("testExecConcurrently")) { + continue; + } + if (annotatn == null || !annotatn.enabled()) { + continue; + } + String[] groups = annotatn.groups(); + if (groups != null && Arrays.asList(groups).contains("WIP")) { + continue; + } + methodsToRun.add(method); + } + + // Execute all the methods many times + LOG.info("Executing "+methodsToRun.size()+" methods "+NUM_RUNS+" times each, with "+MAX_EXECUTOR_THREADS+" threads for concurrent execution; max permitted time "+TIMEOUT_MINS+"mins; methods="+methodsToRun); + + List<ListenableFuture<?>> results = Lists.newArrayList(); + for (int i = 0; i < NUM_RUNS; i++) { + for (final Method method : methodsToRun) { + results.add(executor.submit(new Callable<Void>() { + public Void call() throws Exception { + LOG.info("Executing "+method.getName()+" in thread "+Thread.currentThread()); + Stopwatch stopwatch = Stopwatch.createStarted(); + try { + method.invoke(WinRmMachineLocationLiveTest.this); + LOG.info("Executed "+method.getName()+" in "+Time.makeTimeStringRounded(stopwatch)+", in thread "+Thread.currentThread()+"; total "+counter.incrementAndGet()+" methods done"); + return null; + } catch (Exception e) { + LOG.error("Execute failed for "+method.getName()+" after "+Time.makeTimeStringRounded(stopwatch)+", in thread "+Thread.currentThread()+"; total "+counter.incrementAndGet()+" methods done"); + throw e; + } + }})); + } + } + + Futures.allAsList(results).get(TIMEOUT_MINS, TimeUnit.MINUTES); + } + + private void assertExecFails(String cmd) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertFailed(cmd, machine.executeScript(cmd), stopwatch); + } + + private void assertExecFails(List<String> cmds) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertFailed(cmds, machine.executeScript(cmds), stopwatch); + } + + private void assertExecPsFails(String cmd) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertFailed(cmd, machine.executePsScript(cmd), stopwatch); + } + + private void assertExecPsFails(List<String> cmds) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertFailed(cmds, machine.executePsScript(cmds), stopwatch); + } + + private void assertExecSucceeds(String cmd, String stdout, String stderr) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertSucceeded(cmd, machine.executeScript(cmd), stdout, stderr, stopwatch); + } + + private void assertExecSucceeds(List<String> cmds, String stdout, String stderr) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertSucceeded(cmds, machine.executeScript(cmds), stdout, stderr, stopwatch); + } + + private void assertExecPsSucceeds(String cmd, String stdout, String stderr) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertSucceeded(cmd, machine.executePsScript(cmd), stdout, stderr, stopwatch); + } + + private void assertExecPsSucceeds(List<String> cmds, String stdout, String stderr) { + Stopwatch stopwatch = Stopwatch.createStarted(); + assertSucceeded(cmds, machine.executePsScript(cmds), stdout, stderr, stopwatch); + } + + private void assertFailed(Object cmd, WinRmToolResponse response, Stopwatch stopwatch) { + String msg = "statusCode="+response.getStatusCode()+"; out="+response.getStdOut()+"; err="+response.getStdErr(); + LOG.info("Executed in "+Time.makeTimeStringRounded(stopwatch)+" (asserting failed): "+msg+"; cmd="+cmd); + assertNotEquals(response.getStatusCode(), 0, msg); + } + + private WinRmToolResponse assertSucceeded(Object cmd, WinRmToolResponse response, String stdout, String stderr, Stopwatch stopwatch) { + String msg = "statusCode="+response.getStatusCode()+"; out="+response.getStdOut()+"; err="+response.getStdErr(); + LOG.info("Executed in "+Time.makeTimeStringRounded(stopwatch)+" (asserting success): "+msg+"; cmd="+cmd); + assertEquals(response.getStatusCode(), 0, msg); + if (stdout != null) assertEquals(response.getStdOut().trim(), stdout, msg); + if (stderr != null) assertEquals(response.getStdErr().trim(), stderr, msg); + return response; } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WindowsTestFixture.java ---------------------------------------------------------------------- diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WindowsTestFixture.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WindowsTestFixture.java new file mode 100644 index 0000000..10aa4b7 --- /dev/null +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/test/location/WindowsTestFixture.java @@ -0,0 +1,71 @@ +/* + * 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.entity.software.base.test.location; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.location.jclouds.JcloudsLocation; +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class WindowsTestFixture { + + @SuppressWarnings("unchecked") + public static MachineProvisioningLocation<WinRmMachineLocation> setUpWindowsLocation(ManagementContext mgmt) throws Exception { + // Commented out / unused code included here to make it easy to supply a + // pre-existing Windows VM for use in a bunch of different tests. +// return (MachineProvisioningLocation<WinRmMachineLocation>) newByonLocation((ManagementContextInternal) mgmt); + return (MachineProvisioningLocation<WinRmMachineLocation>) newJcloudsLocation((ManagementContextInternal) mgmt); + } + + private static MachineProvisioningLocation<?> newJcloudsLocation(ManagementContextInternal mgmt) { + // Requires no userMetadata to be set, so that we use WinRmMachineLocation.getDefaultUserMetadataString() + mgmt.getBrooklynProperties().remove("brooklyn.location.jclouds.aws-ec2.userMetadata"); + mgmt.getBrooklynProperties().remove("brooklyn.location.jclouds.userMetadata"); + mgmt.getBrooklynProperties().remove("brooklyn.location.userMetadata"); + + return (JcloudsLocation) mgmt.getLocationRegistry().resolve("jclouds:aws-ec2:us-west-2", ImmutableMap.<String, Object>builder() + .put("inboundPorts", ImmutableList.of(5985, 3389)) + .put("displayName", "AWS Oregon (Windows)") + .put("imageOwner", "801119661308") + .put("imageNameRegex", "Windows_Server-2012-R2_RTM-English-64Bit-Base-.*") + .put("hardwareId", "m3.medium") + .put("useJcloudsSshInit", false) + .build()); + } + + @SuppressWarnings("unused") + private static MachineProvisioningLocation<?> newByonLocation(ManagementContextInternal mgmt) { + Map<String, String> config = new LinkedHashMap<>(); + config.put("hosts", "52.12.211.123:5985"); + config.put("osFamily", "windows"); + config.put("winrm", "52.12.211.123:5985"); + config.put("user", "Administrator"); + config.put("password", "pa55w0rd"); + config.put("useJcloudsSshInit", "false"); + config.put("byonIdentity", "123"); + return (MachineProvisioningLocation<?>) mgmt.getLocationRegistry().resolve("byon", config); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/pom.xml ---------------------------------------------------------------------- diff --git a/usage/camp/pom.xml b/usage/camp/pom.xml index 911ff6a..fb5d7ee 100644 --- a/usage/camp/pom.xml +++ b/usage/camp/pom.xml @@ -157,6 +157,12 @@ </dependency> <dependency> <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-locations-jclouds</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.brooklyn</groupId> <artifactId>brooklyn-test-support</artifactId> <version>${project.version}</version> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/WindowsYamlLiveTest.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/WindowsYamlLiveTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/WindowsYamlLiveTest.java new file mode 100644 index 0000000..15626db --- /dev/null +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/WindowsYamlLiveTest.java @@ -0,0 +1,410 @@ +/* + * 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.camp.brooklyn; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.io.StringReader; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.api.mgmt.HasTaskChildren; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.core.entity.Attributes; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.entity.software.base.SoftwareProcess; +import org.apache.brooklyn.entity.software.base.VanillaWindowsProcess; +import org.apache.brooklyn.entity.software.base.test.location.WindowsTestFixture; +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.util.core.task.TaskPredicates; +import org.apache.brooklyn.util.text.StringPredicates; +import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +/** + * Tests Windows YAML blueprint features. + */ +@Test +public class WindowsYamlLiveTest extends AbstractYamlTest { + + // TODO Remove duplication of assertStreams and VanillaWindowsProcessWinrmStreamsLiveTest.assertStreams + + private static final Logger log = LoggerFactory.getLogger(WindowsYamlLiveTest.class); + + /** + * Maps from the task names that are used to the names used in log/exception messages. + */ + private static final Map<String, String> TASK_REGEX_TO_COMMAND = ImmutableMap.<String, String>builder() + .put("winrm: pre-install-command.*", "pre-install-command") + .put("winrm: install.*", "install-command") + .put("winrm: post-install-command.*", "post-install-command") + .put("winrm: customize.*", "customize-command") + .put("winrm: pre-launch-command.*", "pre-launch-command") + .put("winrm: launch.*", "launch-command") + .put("winrm: post-launch-command.*", "post-launch-command") + .put("winrm: stop-command.*", "stop-command") + .put("winrm: is-running-command.*", "is-running-command") + .build(); + + protected List<String> yamlLocation; + protected MachineProvisioningLocation<WinRmMachineLocation> location; + protected WinRmMachineLocation machine; + protected Entity app; + + @BeforeClass(alwaysRun = true) + public void setUpClass() throws Exception { + super.setUp(); + + location = WindowsTestFixture.setUpWindowsLocation(mgmt()); + machine = (WinRmMachineLocation) location.obtain(ImmutableMap.of()); + String ip = machine.getAddress().getHostAddress(); + String password = machine.config().get(WinRmMachineLocation.PASSWORD); + + yamlLocation = ImmutableList.of( + "location:", + " byon:", + " hosts:", + " - winrm: "+ip+":5985", + " password: "+password, + " user: Administrator", + " osFamily: windows"); + } + + @AfterClass(alwaysRun = true) + public void tearDownClass() { + try { + if (location != null) location.release(machine); + } catch (Throwable t) { + log.error("Caught exception in tearDownClass method", t); + } finally { + super.tearDown(); + } + } + + @BeforeMethod(alwaysRun = true) + @Override + public void setUp() { + // no-op; everything done @BeforeClass + } + + @AfterMethod(alwaysRun = true) + @Override + public void tearDown() { + try { + if (app != null) Entities.destroy(app); + } catch (Throwable t) { + log.error("Caught exception in tearDown method", t); + } finally { + app = null; + } + } + + @Override + protected ManagementContextInternal mgmt() { + return (ManagementContextInternal) super.mgmt(); + } + + @Test(groups="Live") + public void testPowershellMinimalist() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("checkRunning.powershell.command", "\"& c:\\\\exit0.bat\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.of(); + + runWindowsApp(cmds, stdouts, null); + } + + @Test(groups="Live") + public void testPowershell() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("pre.install.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("install.powershell.command", "\"& c:\\\\echoMyArg.ps1 -myarg myInstall\"") + .put("post.install.powershell.command", "\"& c:\\\\echoArg.bat myPostInstall\"") + .put("customize.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.bat\"") + .put("pre.launch.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.ps1\"") + .put("launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("post.launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("checkRunning.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("stop.powershell.command", "\"& c:\\\\exit0.ps1\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.<String, List<String>>builder() + .put("winrm: install.*", ImmutableList.of("myInstall")) + .put("winrm: post-install-command.*", ImmutableList.of("myPostInstall")) + .put("winrm: customize.*", ImmutableList.of("myval")) + .put("winrm: pre-launch-command.*", ImmutableList.of("myval")) + .build(); + + runWindowsApp(cmds, stdouts, null); + } + + @Test(groups="Live") + public void testBatch() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("pre.install.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\exit0.ps1\"") + .put("install.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\echoMyArg.ps1 -myarg myInstall\"") + .put("post.install.command", "\"c:\\\\echoArg.bat myPostInstall\"") + .put("customize.command", "\"c:\\\\echoFreemarkerMyarg.bat\"") + .put("pre.launch.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\echoFreemarkerMyarg.ps1\"") + .put("launch.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\exit0.ps1\"") + .put("post.launch.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\exit0.ps1\"") + .put("checkRunning.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\exit0.ps1\"") + .put("stop.command", "\"PowerShell -NonInteractive -NoProfile -Command c:\\\\exit0.ps1\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.<String, List<String>>builder() + .put("winrm: install.*", ImmutableList.of("myInstall")) + .put("winrm: post-install-command.*", ImmutableList.of("myPostInstall")) + .put("winrm: customize.*", ImmutableList.of("myval")) + .put("winrm: pre-launch-command.*", ImmutableList.of("myval")) + .build(); + + runWindowsApp(cmds, stdouts, null); + } + + @Test(groups="Live") + public void testPowershellExit1() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("pre.install.powershell.command", "\"& c:\\\\exit1.ps1\"") + .put("install.powershell.command", "\"& c:\\\\echoMyArg.ps1 -myarg myInstall\"") + .put("post.install.powershell.command", "\"& c:\\\\echoArg.bat myPostInstall\"") + .put("customize.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.bat\"") + .put("pre.launch.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.ps1\"") + .put("launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("post.launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("checkRunning.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("stop.powershell.command", "\"& c:\\\\exit0.ps1\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.of(); + + runWindowsApp(cmds, stdouts, "winrm: pre-install-command.*"); + } + + // FIXME Failing to match the expected exception, but looks fine! Needs more investigation. + @Test(groups="Live") + public void testPowershellCheckRunningExit1() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("pre.install.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("install.powershell.command", "\"& c:\\\\echoMyArg.ps1 -myarg myInstall\"") + .put("post.install.powershell.command", "\"& c:\\\\echoArg.bat myPostInstall\"") + .put("customize.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.bat\"") + .put("pre.launch.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.ps1\"") + .put("launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("post.launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("checkRunning.powershell.command", "\"& c:\\\\exit1.ps1\"") + .put("stop.powershell.command", "\"& c:\\\\exit0.ps1\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.of(); + + runWindowsApp(cmds, stdouts, "winrm: is-running-command.*"); + } + + // FIXME Needs more work to get the stop's task that failed, so can assert got the right error message + @Test(groups="Live") + public void testPowershellStopExit1() throws Exception { + Map<String, String> cmds = ImmutableMap.<String, String>builder() + .put("myarg", "myval") + .put("pre.install.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("install.powershell.command", "\"& c:\\\\echoMyArg.ps1 -myarg myInstall\"") + .put("post.install.powershell.command", "\"& c:\\\\echoArg.bat myPostInstall\"") + .put("customize.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.bat\"") + .put("pre.launch.powershell.command", "\"& c:\\\\echoFreemarkerMyarg.ps1\"") + .put("launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("post.launch.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("checkRunning.powershell.command", "\"& c:\\\\exit0.ps1\"") + .put("stop.powershell.command", "\"& c:\\\\exit1.ps1\"") + .build(); + + Map<String, List<String>> stdouts = ImmutableMap.of(); + + runWindowsApp(cmds, stdouts, "winrm: stop-command.*"); + } + + protected void runWindowsApp(Map<String, String> commands, Map<String, List<String>> stdouts, String taskRegexFailed) throws Exception { + String cmdFailed = (taskRegexFailed == null) ? null : TASK_REGEX_TO_COMMAND.get(taskRegexFailed); + + List<String> yaml = Lists.newArrayList(); + yaml.addAll(yamlLocation); + yaml.addAll(ImmutableList.of( + "services:", + "- type: org.apache.brooklyn.entity.software.base.VanillaWindowsProcess", + " brooklyn.config:", + " onbox.base.dir.skipResolution: true", + " templates.preinstall:", + " classpath://org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.bat: c:\\echoFreemarkerMyarg.bat", + " classpath://org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.ps1: c:\\echoFreemarkerMyarg.ps1", + " files.preinstall:", + " classpath://org/apache/brooklyn/camp/brooklyn/echoArg.bat: c:\\echoArg.bat", + " classpath://org/apache/brooklyn/camp/brooklyn/echoMyArg.ps1: c:\\echoMyArg.ps1", + " classpath://org/apache/brooklyn/camp/brooklyn/exit0.bat: c:\\exit0.bat", + " classpath://org/apache/brooklyn/camp/brooklyn/exit1.bat: c:\\exit1.bat", + " classpath://org/apache/brooklyn/camp/brooklyn/exit0.ps1: c:\\exit0.ps1", + " classpath://org/apache/brooklyn/camp/brooklyn/exit1.ps1: c:\\exit1.ps1", + "")); + + for (Map.Entry<String, String> entry : commands.entrySet()) { + yaml.add(" "+entry.getKey()+": "+entry.getValue()); + } + + if (Strings.isBlank(cmdFailed)) { + app = createAndStartApplication(new StringReader(Joiner.on("\n").join(yaml))); + waitForApplicationTasks(app); + log.info("App started:"); + Entities.dumpInfo(app); + + VanillaWindowsProcess entity = (VanillaWindowsProcess) app.getChildren().iterator().next(); + + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true); + assertStreams(entity, stdouts); + + } else if (cmdFailed.equals("stop-command")) { + app = createAndStartApplication(new StringReader(Joiner.on("\n").join(yaml))); + waitForApplicationTasks(app); + log.info("App started:"); + Entities.dumpInfo(app); + VanillaWindowsProcess entity = (VanillaWindowsProcess) app.getChildren().iterator().next(); + EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true); + + entity.stop(); + assertSubTaskFailures(entity, ImmutableMap.of(taskRegexFailed, StringPredicates.containsLiteral("for "+cmdFailed))); + + } else { + try { + app = createAndStartApplication(new StringReader(Joiner.on("\n").join(yaml))); + fail("start should have failed for app="+app); + } catch (Exception e) { + if (e.toString().contains("invalid result") && e.toString().contains("for "+cmdFailed)) throw e; + } + } + } + + protected void assertStreams(SoftwareProcess entity, Map<String, List<String>> stdouts) { + Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(mgmt().getExecutionManager(), entity); + + for (Map.Entry<String, List<String>> entry : stdouts.entrySet()) { + String taskNameRegex = entry.getKey(); + List<String> expectedOuts = entry.getValue(); + + Task<?> subTask = findTaskOrSubTask(tasks, TaskPredicates.displayNameMatches(StringPredicates.matchesRegex(taskNameRegex))).get(); + + String stdin = getStreamOrFail(subTask, BrooklynTaskTags.STREAM_STDIN); + String stdout = getStreamOrFail(subTask, BrooklynTaskTags.STREAM_STDOUT); + String stderr = getStreamOrFail(subTask, BrooklynTaskTags.STREAM_STDERR); + String env = getStream(subTask, BrooklynTaskTags.STREAM_ENV); + String msg = "stdin="+stdin+"; stdout="+stdout+"; stderr="+stderr+"; env="+env; + + for (String expectedOut : expectedOuts) { + assertTrue(stdout.contains(expectedOut), msg); + } + } + } + + protected void assertSubTaskFailures(SoftwareProcess entity, Map<String, Predicate<CharSequence>> taskErrs) throws Exception { + Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(mgmt().getExecutionManager(), entity); + + for (Map.Entry<String, Predicate<CharSequence>> entry : taskErrs.entrySet()) { + String taskNameRegex = entry.getKey(); + Predicate<? super String> errChecker = entry.getValue(); + Task<?> subTask = findTaskOrSubTask(tasks, TaskPredicates.displayNameMatches(StringPredicates.matchesRegex(taskNameRegex))).get(); + String msg = "regex="+taskNameRegex+"; task="+subTask; + assertNotNull(subTask, msg); + assertTrue(subTask.isDone(), msg); + assertTrue(subTask.isError(), msg); + try { + subTask.get(); + fail(); + } catch (Exception e) { + if (!errChecker.apply(e.toString())) { + throw e; + } + } + } + } + + public static String getStreamOrFail(Task<?> task, String streamType) { + String msg = "task="+task+"; stream="+streamType; + BrooklynTaskTags.WrappedStream stream = checkNotNull(BrooklynTaskTags.stream(task, streamType), "Stream null: " + msg); + return checkNotNull(stream.streamContents.get(), "Contents null: "+msg); + } + + public static String getStream(Task<?> task, String streamType) { + BrooklynTaskTags.WrappedStream stream = BrooklynTaskTags.stream(task, streamType); + return (stream != null) ? stream.streamContents.get() : null; + } + + protected Optional<Task<?>> findTaskOrSubTask(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher) { + List<String> taskNames = Lists.newArrayList(); + Optional<Task<?>> result = findTaskOrSubTaskImpl(tasks, matcher, taskNames); + if (!result.isPresent() && log.isDebugEnabled()) { + log.debug("Task not found matching "+matcher+"; contender names were "+taskNames); + } + return result; + } + + protected Optional<Task<?>> findTaskOrSubTaskImpl(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher, List<String> taskNames) { + for (Task<?> task : tasks) { + if (matcher.apply(task)) return Optional.<Task<?>>of(task); + + if (!(task instanceof HasTaskChildren)) { + return Optional.absent(); + } else { + Optional<Task<?>> subResult = findTaskOrSubTask(((HasTaskChildren) task).getChildren(), matcher); + if (subResult.isPresent()) return subResult; + } + } + + return Optional.<Task<?>>absent(); + } + + @Override + protected Logger getLogger() { + return log; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoArg.bat ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoArg.bat b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoArg.bat new file mode 100644 index 0000000..dd77ba6 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoArg.bat @@ -0,0 +1,19 @@ +REM Licensed to the Apache Software Foundation (ASF) under one +REM or more contributor license agreements. See the NOTICE file +REM distributed with this work for additional information +REM regarding copyright ownership. The ASF licenses this file +REM to you under the Apache License, Version 2.0 (the +REM "License"); you may not use this file except in compliance +REM with the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, +REM software distributed under the License is distributed on an +REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +REM KIND, either express or implied. See the License for the +REM specific language governing permissions and limitations +REM under the License. + +@ECHO OFF +echo %1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.bat ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.bat b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.bat new file mode 100644 index 0000000..33f7b7e --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.bat @@ -0,0 +1,18 @@ +REM Licensed to the Apache Software Foundation (ASF) under one +REM or more contributor license agreements. See the NOTICE file +REM distributed with this work for additional information +REM regarding copyright ownership. The ASF licenses this file +REM to you under the Apache License, Version 2.0 (the +REM "License"); you may not use this file except in compliance +REM with the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, +REM software distributed under the License is distributed on an +REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +REM KIND, either express or implied. See the License for the +REM specific language governing permissions and limitations +REM under the License. + +echo ${config['myarg']} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.ps1 ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.ps1 b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.ps1 new file mode 100644 index 0000000..c2535ea --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoFreemarkerMyarg.ps1 @@ -0,0 +1,18 @@ +# 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. + +Write-Host ${config['myarg']} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoMyArg.ps1 ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoMyArg.ps1 b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoMyArg.ps1 new file mode 100644 index 0000000..3a2d33d --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/echoMyArg.ps1 @@ -0,0 +1,22 @@ +# 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. + +param( + [string]$myarg +) + +Write-Host $myarg http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.bat ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.bat b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.bat new file mode 100644 index 0000000..2a926b6 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.bat @@ -0,0 +1,18 @@ +REM Licensed to the Apache Software Foundation (ASF) under one +REM or more contributor license agreements. See the NOTICE file +REM distributed with this work for additional information +REM regarding copyright ownership. The ASF licenses this file +REM to you under the Apache License, Version 2.0 (the +REM "License"); you may not use this file except in compliance +REM with the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, +REM software distributed under the License is distributed on an +REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +REM KIND, either express or implied. See the License for the +REM specific language governing permissions and limitations +REM under the License. + +EXIT /B 0 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.ps1 ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.ps1 b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.ps1 new file mode 100644 index 0000000..fe0e1f1 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit0.ps1 @@ -0,0 +1,18 @@ +# 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. + +exit 0 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.bat ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.bat b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.bat new file mode 100644 index 0000000..f8b79b9 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.bat @@ -0,0 +1,18 @@ +REM Licensed to the Apache Software Foundation (ASF) under one +REM or more contributor license agreements. See the NOTICE file +REM distributed with this work for additional information +REM regarding copyright ownership. The ASF licenses this file +REM to you under the Apache License, Version 2.0 (the +REM "License"); you may not use this file except in compliance +REM with the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, +REM software distributed under the License is distributed on an +REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +REM KIND, either express or implied. See the License for the +REM specific language governing permissions and limitations +REM under the License. + +EXIT /B 1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/10071a92/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.ps1 ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.ps1 b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.ps1 new file mode 100644 index 0000000..a7fc049 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/exit1.ps1 @@ -0,0 +1,19 @@ +# 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. + +Write-Host single line file gives exit code 0 from PyWinRM +exit 1 \ No newline at end of file
