/* * 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.core.effector.ssh; import java.io.File; import java.io.IOException; import java.util.Arrays; import org.apache.brooklyn.api.location.LocationSpec; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.TaskAdaptable; import org.apache.brooklyn.api.mgmt.TaskFactory; import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; import org.apache.brooklyn.core.effector.ssh.SshEffectorTasksTest; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.test.entity.TestApplication; import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper; import org.apache.brooklyn.util.core.task.ssh.SshPutTaskWrapper; import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException; import org.apache.brooklyn.util.net.Urls; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; import org.apache.brooklyn.location.ssh.SshMachineLocation; import com.google.common.io.Files; public class SshEffectorTasksTest { private static final Logger log = LoggerFactory.getLogger(SshEffectorTasksTest.class); TestApplication app; ManagementContext mgmt; SshMachineLocation host; File tempDir; boolean failureExpected; @BeforeMethod(alwaysRun=true) public void setup() throws Exception { app = TestApplication.Factory.newManagedInstanceForTests(); mgmt = app.getManagementContext(); LocalhostMachineProvisioningLocation lhc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); host = lhc.obtain(); app.start(Arrays.asList(host)); clearExpectedFailure(); tempDir = Files.createTempDir(); } @AfterMethod(alwaysRun=true) public void tearDown() throws Exception { if (mgmt != null) Entities.destroyAll(mgmt); mgmt = null; FileUtils.deleteDirectory(tempDir); checkExpectedFailure(); } protected void checkExpectedFailure() { if (failureExpected) { clearExpectedFailure(); Assert.fail("Test should have thrown an exception but it did not."); } } protected void clearExpectedFailure() { failureExpected = false; } protected void setExpectingFailure() { failureExpected = true; } public <T extends TaskAdaptable<?>> T submit(final TaskFactory<T> taskFactory) { return Entities.submit(app, taskFactory); } // ------------------- basic ssh @Test(groups="Integration") public void testSshEchoHello() { ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.ssh("sleep 1 ; echo hello world")); Assert.assertFalse(t.isDone()); Assert.assertEquals(t.get(), (Integer)0); Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0); Assert.assertEquals(t.getStdout().trim(), "hello world"); } @Test(groups="Integration") public void testSshPut() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "f1"); SshPutTaskWrapper t = submit(SshEffectorTasks.put(fn).contents("hello world")); t.block(); Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world"); // and make sure this doesn't throw Assert.assertTrue(t.isDone()); Assert.assertTrue(t.isSuccessful()); Assert.assertEquals(t.get(), null); Assert.assertEquals(t.getExitCode(), (Integer)0); } @Test(groups="Integration") public void testSshFetch() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "f2"); FileUtils.write(new File(fn), "hello fetched world"); SshFetchTaskWrapper t = submit(SshEffectorTasks.fetch(fn)); t.block(); Assert.assertTrue(t.isDone()); Assert.assertEquals(t.get(), "hello fetched world"); } // ----------------- pid stuff @Test(groups="Integration") public void testNonRunningPid() { ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidRunning(99999)); Assert.assertNotEquals(t.getTask().getUnchecked(), (Integer)0); Assert.assertNotEquals(t.getExitCode(), (Integer)0); ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidRunning(99999)); Assert.assertFalse(t2.getTask().getUnchecked()); } @Test(groups="Integration") public void testNonRunningPidRequired() { ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidRunning(99999)); setExpectingFailure(); try { t.getTask().getUnchecked(); } catch (Exception e) { log.info("The error if required PID is not found is: "+e); clearExpectedFailure(); Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e); } checkExpectedFailure(); } public static Integer getMyPid() { try { java.lang.management.RuntimeMXBean runtime = java.lang.management.ManagementFactory.getRuntimeMXBean(); java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm"); jvm.setAccessible(true); // sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); Object mgmt = jvm.get(runtime); java.lang.reflect.Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); pid_method.setAccessible(true); return (Integer) pid_method.invoke(mgmt); } catch (Exception e) { throw new PropagatedRuntimeException("Test depends on (fragile) getMyPid method which does not work here", e); } } @Test(groups="Integration") public void testRunningPid() { ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidRunning(getMyPid())); Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0); ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidRunning(getMyPid())); Assert.assertTrue(t2.getTask().getUnchecked()); } @Test(groups="Integration") public void testRunningPidFromFile() throws IOException { File f = File.createTempFile("testBrooklynPid", ".pid"); Files.write( (""+getMyPid()).getBytes(), f ); ProcessTaskWrapper<Integer> t = submit(SshEffectorTasks.codePidFromFileRunning(f.getPath())); Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0); ProcessTaskWrapper<Boolean> t2 = submit(SshEffectorTasks.isPidFromFileRunning(f.getPath())); Assert.assertTrue(t2.getTask().getUnchecked()); } @Test(groups="Integration") public void testRequirePidFromFileOnFailure() throws IOException { File f = File.createTempFile("testBrooklynPid", ".pid"); Files.write( "99999".getBytes(), f ); ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath())); setExpectingFailure(); try { t.getTask().getUnchecked(); } catch (Exception e) { log.info("The error if required PID is not found is: "+e); clearExpectedFailure(); Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e); Assert.assertEquals(t.getExitCode(), (Integer)1); } checkExpectedFailure(); } @Test(groups="Integration") public void testRequirePidFromFileOnFailureNoSuchFile() throws IOException { ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning("/path/does/not/exist/SADVQW")); setExpectingFailure(); try { t.getTask().getUnchecked(); } catch (Exception e) { log.info("The error if required PID is not found is: "+e); clearExpectedFailure(); Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e); Assert.assertEquals(t.getExitCode(), (Integer)1); } checkExpectedFailure(); } @Test(groups="Integration") public void testRequirePidFromFileOnFailureTooManyFiles() throws IOException { ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning("/*")); setExpectingFailure(); try { t.getTask().getUnchecked(); } catch (Exception e) { log.info("The error if required PID is not found is: "+e); clearExpectedFailure(); Assert.assertTrue(e.toString().contains("Process with PID"), "Expected nice clue in error but got: "+e); Assert.assertEquals(t.getExitCode(), (Integer)2); } checkExpectedFailure(); } @Test(groups="Integration") public void testRequirePidFromFileOnSuccess() throws IOException { File f = File.createTempFile("testBrooklynPid", ".pid"); Files.write( (""+getMyPid()).getBytes(), f ); ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath())); t.getTask().getUnchecked(); } @Test(groups="Integration") public void testRequirePidFromFileOnSuccessAcceptsWildcards() throws IOException { File f = File.createTempFile("testBrooklynPid", ".pid"); Files.write( (""+getMyPid()).getBytes(), f ); ProcessTaskWrapper<?> t = submit(SshEffectorTasks.requirePidFromFileRunning(f.getPath()+"*")); t.getTask().getUnchecked(); } }