/* * 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.util.core.task.ssh; import java.io.File; import java.io.IOException; import org.apache.brooklyn.api.location.LocationSpec; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.core.effector.ssh.SshEffectorTasksTest; import org.apache.brooklyn.core.entity.BrooklynConfigKeys; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; 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 org.apache.brooklyn.util.core.ssh.BashCommandsIntegrationTest; import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskFactory; import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper; import org.apache.brooklyn.util.core.task.ssh.SshPutTaskFactory; import org.apache.brooklyn.util.core.task.ssh.SshPutTaskWrapper; import org.apache.brooklyn.util.core.task.ssh.SshTasks; import org.apache.brooklyn.util.core.task.ssh.SshTasksTest; import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; import org.apache.brooklyn.util.net.Urls; import org.apache.brooklyn.util.os.Os; /** * Some tests for {@link SshTasks}. Note more tests in {@link BashCommandsIntegrationTest}, * {@link SshEffectorTasksTest}, and {@link SoftwareEffectorTest}. */ public class SshTasksTest { private static final Logger log = LoggerFactory.getLogger(SshTasksTest.class); ManagementContext mgmt; SshMachineLocation host; File tempDir; boolean failureExpected; @BeforeMethod(alwaysRun=true) public void setup() throws Exception { mgmt = new LocalManagementContext(); LocalhostMachineProvisioningLocation lhc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); host = lhc.obtain(); clearExpectedFailure(); tempDir = Os.newTempDir(getClass()); } @AfterMethod(alwaysRun=true) public void tearDown() throws Exception { if (mgmt != null) Entities.destroyAll(mgmt); mgmt = null; tempDir = Os.deleteRecursively(tempDir).asNullOrThrowing(); 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; } protected <T> ProcessTaskWrapper<T> submit(final ProcessTaskFactory<T> tf) { tf.machine(host); ProcessTaskWrapper<T> t = tf.newTask(); mgmt.getExecutionManager().submit(t); return t; } protected SshPutTaskWrapper submit(final SshPutTaskFactory tf) { SshPutTaskWrapper t = tf.newTask(); mgmt.getExecutionManager().submit(t); return t; } @Test(groups="Integration") public void testSshEchoHello() { ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "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 testCopyTo() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "f1"); SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, 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 testCopyToFailBadSubdir() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file"); SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world")); //this doesn't fail t.block(); Assert.assertTrue(t.isDone()); setExpectingFailure(); try { // but this does t.get(); } catch (Exception e) { log.info("The error if file cannot be written is: "+e); clearExpectedFailure(); } checkExpectedFailure(); // and the results indicate failure Assert.assertFalse(t.isSuccessful()); Assert.assertNotNull(t.getException()); Assert.assertNotEquals(t.getExitCode(), (Integer)0); } @Test(groups="Integration") public void testCopyToFailBadSubdirAllow() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file"); SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").allowFailure()); //this doesn't fail t.block(); Assert.assertTrue(t.isDone()); // and this doesn't fail either Assert.assertEquals(t.get(), null); // but it's not successful Assert.assertNotNull(t.getException()); Assert.assertFalse(t.isSuccessful()); // exit code probably null, but won't be zero Assert.assertNotEquals(t.getExitCode(), (Integer)0); } @Test(groups="Integration") public void testCopyToFailBadSubdirCreate() throws IOException { String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir-to-create/file"); SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").createDirectory()); t.block(); // directory should be created, and file readable now Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world"); 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"); SshFetchTaskFactory tf = SshTasks.newSshFetchTaskFactory(host, fn); SshFetchTaskWrapper t = tf.newTask(); mgmt.getExecutionManager().submit(t); t.block(); Assert.assertTrue(t.isDone()); Assert.assertEquals(t.get(), "hello fetched world"); Assert.assertEquals(t.getBytes(), "hello fetched world".getBytes()); } @Test(groups="Integration") public void testSshWithHeaderProperty() { host.config().set(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n"); ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "echo bar")); Assert.assertTrue(t.block().getStdout().trim().matches("foo\\s+bar"), "mismatched output was: "+t.getStdout()); } @Test(groups="Integration") public void testSshIgnoringHeaderProperty() { host.config().set(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n"); ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, false, "echo bar")); Assert.assertTrue(t.block().getStdout().trim().matches("bar"), "mismatched output was: "+t.getStdout()); } }