launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 gc "launchpad.net/gocheck" 9 "os" 10 "path/filepath" 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 newPath := s.testbin + ":" + os.Getenv("PATH") 31 s.PatchEnvironment("PATH", newPath) 32 } 33 34 func (s *ExecuteSSHCommandSuite) fakeSSH(c *gc.C, cmd string) { 35 err := ioutil.WriteFile(s.fakessh, []byte(cmd), 0755) 36 c.Assert(err, gc.IsNil) 37 } 38 39 func (s *ExecuteSSHCommandSuite) TestCaptureOutput(c *gc.C) { 40 s.fakeSSH(c, echoSSH) 41 42 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 43 Host: "hostname", 44 Command: "sudo apt-get update\nsudo apt-get upgrade", 45 Timeout: testing.ShortWait, 46 }) 47 48 c.Assert(err, gc.IsNil) 49 c.Assert(response.Code, gc.Equals, 0) 50 c.Assert(string(response.Stdout), gc.Equals, "sudo apt-get update\nsudo apt-get upgrade\n") 51 c.Assert(string(response.Stderr), gc.Equals, 52 "-o StrictHostKeyChecking no -o PasswordAuthentication no hostname -- /bin/bash -s\n") 53 } 54 55 func (s *ExecuteSSHCommandSuite) TestIdentityFile(c *gc.C) { 56 s.fakeSSH(c, echoSSH) 57 58 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 59 IdentityFile: "identity-file", 60 Host: "hostname", 61 Timeout: testing.ShortWait, 62 }) 63 64 c.Assert(err, gc.IsNil) 65 c.Assert(string(response.Stderr), jc.Contains, " -i identity-file ") 66 } 67 68 func (s *ExecuteSSHCommandSuite) TestTimoutCaptureOutput(c *gc.C) { 69 s.fakeSSH(c, slowSSH) 70 71 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 72 IdentityFile: "identity-file", 73 Host: "hostname", 74 Command: "ignored", 75 Timeout: testing.ShortWait, 76 }) 77 78 c.Check(err, gc.ErrorMatches, "command timed out") 79 c.Assert(response.Code, gc.Equals, 0) 80 c.Assert(string(response.Stdout), gc.Equals, "stdout\n") 81 c.Assert(string(response.Stderr), gc.Equals, "stderr\n") 82 } 83 84 func (s *ExecuteSSHCommandSuite) TestCapturesReturnCode(c *gc.C) { 85 s.fakeSSH(c, passthroughSSH) 86 87 response, err := ssh.ExecuteCommandOnMachine(ssh.ExecParams{ 88 IdentityFile: "identity-file", 89 Host: "hostname", 90 Command: "echo stdout; exit 42", 91 Timeout: testing.ShortWait, 92 }) 93 94 c.Check(err, gc.IsNil) 95 c.Assert(response.Code, gc.Equals, 42) 96 c.Assert(string(response.Stdout), gc.Equals, "stdout\n") 97 c.Assert(string(response.Stderr), gc.Equals, "") 98 } 99 100 // echoSSH outputs the command args to stderr, and copies stdin to stdout 101 var echoSSH = `#!/bin/bash 102 # Write the args to stderr 103 echo "$*" >&2 104 cat /dev/stdin 105 ` 106 107 // slowSSH sleeps for a while after outputting some text to stdout and stderr 108 var slowSSH = `#!/bin/bash 109 echo "stderr" >&2 110 echo "stdout" 111 sleep 5s 112 ` 113 114 // passthroughSSH creates an ssh that executes stdin. 115 var passthroughSSH = `#!/bin/bash -s`