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