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