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`