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`