github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/utils/ssh/run_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package ssh_test 5 6 import ( 7 "io/ioutil" 8 "path/filepath" 9 10 gc "launchpad.net/gocheck" 11 12 "launchpad.net/juju-core/testing" 13 jc "launchpad.net/juju-core/testing/checkers" 14 "launchpad.net/juju-core/testing/testbase" 15 "launchpad.net/juju-core/utils/ssh" 16 ) 17 18 type ExecuteSSHCommandSuite struct { 19 testbase.LoggingSuite 20 testbin string 21 fakessh string 22 } 23 24 var _ = gc.Suite(&ExecuteSSHCommandSuite{}) 25 26 func (s *ExecuteSSHCommandSuite) SetUpTest(c *gc.C) { 27 s.LoggingSuite.SetUpTest(c) 28 s.testbin = c.MkDir() 29 s.fakessh = filepath.Join(s.testbin, "ssh") 30 s.PatchEnvPathPrepend(s.testbin) 31 } 32 33 func (s *ExecuteSSHCommandSuite) fakeSSH(c *gc.C, cmd string) { 34 err := ioutil.WriteFile(s.fakessh, []byte(cmd), 0755) 35 c.Assert(err, gc.IsNil) 36 } 37 38 func (s *ExecuteSSHCommandSuite) TestCaptureOutput(c *gc.C) { 39 s.fakeSSH(c, echoSSH) 40 41 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 42 Host: "hostname", 43 Command: "sudo apt-get update\nsudo apt-get upgrade", 44 Timeout: testing.ShortWait, 45 }) 46 47 c.Assert(err, gc.IsNil) 48 c.Assert(response.Code, gc.Equals, 0) 49 c.Assert(string(response.Stdout), gc.Equals, "sudo apt-get update\nsudo apt-get upgrade\n") 50 c.Assert(string(response.Stderr), gc.Equals, 51 "-o StrictHostKeyChecking no -o PasswordAuthentication no hostname /bin/bash -s\n") 52 } 53 54 func (s *ExecuteSSHCommandSuite) TestIdentityFile(c *gc.C) { 55 s.fakeSSH(c, echoSSH) 56 57 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 58 IdentityFile: "identity-file", 59 Host: "hostname", 60 Timeout: testing.ShortWait, 61 }) 62 63 c.Assert(err, gc.IsNil) 64 c.Assert(string(response.Stderr), jc.Contains, " -i identity-file ") 65 } 66 67 func (s *ExecuteSSHCommandSuite) TestTimoutCaptureOutput(c *gc.C) { 68 s.fakeSSH(c, slowSSH) 69 70 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 71 IdentityFile: "identity-file", 72 Host: "hostname", 73 Command: "ignored", 74 Timeout: testing.ShortWait, 75 }) 76 77 c.Check(err, gc.ErrorMatches, "command timed out") 78 c.Assert(response.Code, gc.Equals, 0) 79 c.Assert(string(response.Stdout), gc.Equals, "stdout\n") 80 c.Assert(string(response.Stderr), gc.Equals, "stderr\n") 81 } 82 83 func (s *ExecuteSSHCommandSuite) TestCapturesReturnCode(c *gc.C) { 84 s.fakeSSH(c, passthroughSSH) 85 86 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 87 IdentityFile: "identity-file", 88 Host: "hostname", 89 Command: "echo stdout; exit 42", 90 Timeout: testing.ShortWait, 91 }) 92 93 c.Check(err, gc.IsNil) 94 c.Assert(response.Code, gc.Equals, 42) 95 c.Assert(string(response.Stdout), gc.Equals, "stdout\n") 96 c.Assert(string(response.Stderr), gc.Equals, "") 97 } 98 99 // echoSSH outputs the command args to stderr, and copies stdin to stdout 100 var echoSSH = `#!/bin/bash 101 # Write the args to stderr 102 echo "$*" >&2 103 cat /dev/stdin 104 ` 105 106 // slowSSH sleeps for a while after outputting some text to stdout and stderr 107 var slowSSH = `#!/bin/bash 108 echo "stderr" >&2 109 echo "stdout" 110 sleep 5s 111 ` 112 113 // passthroughSSH creates an ssh that executes stdin. 114 var passthroughSSH = `#!/bin/bash -s`