github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/manual/environ_test.go (about)

     1  // Copyright 2012 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package manual
     5  
     6  import (
     7  	"os"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils/arch"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/constraints"
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/environs/manual"
    18  	"github.com/juju/juju/instance"
    19  	coretesting "github.com/juju/juju/testing"
    20  )
    21  
    22  type baseEnvironSuite struct {
    23  	coretesting.FakeJujuXDGDataHomeSuite
    24  	env *manualEnviron
    25  }
    26  
    27  func (s *baseEnvironSuite) SetUpTest(c *gc.C) {
    28  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    29  	env, err := manualProvider{}.Open(environs.OpenParams{
    30  		Cloud:  CloudSpec(),
    31  		Config: MinimalConfig(c),
    32  	})
    33  	c.Assert(err, jc.ErrorIsNil)
    34  	s.env = env.(*manualEnviron)
    35  }
    36  
    37  type environSuite struct {
    38  	baseEnvironSuite
    39  }
    40  
    41  var _ = gc.Suite(&environSuite{})
    42  
    43  func (s *environSuite) TestInstances(c *gc.C) {
    44  	var ids []instance.Id
    45  
    46  	instances, err := s.env.Instances(ids)
    47  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
    48  	c.Assert(instances, gc.HasLen, 0)
    49  
    50  	ids = append(ids, BootstrapInstanceId)
    51  	instances, err = s.env.Instances(ids)
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	c.Assert(instances, gc.HasLen, 1)
    54  	c.Assert(instances[0], gc.NotNil)
    55  
    56  	ids = append(ids, BootstrapInstanceId)
    57  	instances, err = s.env.Instances(ids)
    58  	c.Assert(err, jc.ErrorIsNil)
    59  	c.Assert(instances, gc.HasLen, 2)
    60  	c.Assert(instances[0], gc.NotNil)
    61  	c.Assert(instances[1], gc.NotNil)
    62  
    63  	ids = append(ids, instance.Id("invalid"))
    64  	instances, err = s.env.Instances(ids)
    65  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
    66  	c.Assert(instances, gc.HasLen, 3)
    67  	c.Assert(instances[0], gc.NotNil)
    68  	c.Assert(instances[1], gc.NotNil)
    69  	c.Assert(instances[2], gc.IsNil)
    70  
    71  	ids = []instance.Id{instance.Id("invalid")}
    72  	instances, err = s.env.Instances(ids)
    73  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
    74  	c.Assert(instances, gc.HasLen, 1)
    75  	c.Assert(instances[0], gc.IsNil)
    76  }
    77  
    78  func (s *environSuite) TestDestroyController(c *gc.C) {
    79  	var resultStdout string
    80  	var resultErr error
    81  	runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) {
    82  		c.Assert(host, gc.Equals, "ubuntu@hostname")
    83  		c.Assert(command, gc.DeepEquals, []string{"sudo", "/bin/bash"})
    84  		c.Assert(stdin, gc.Equals, `
    85  set -x
    86  touch '/var/lib/juju/uninstall-agent'
    87  # If jujud is running, we then wait for a while for it to stop.
    88  stopped=0
    89  if pkill -6 jujud; then
    90      for i in `+"`seq 1 30`"+`; do
    91          if pgrep jujud > /dev/null ; then
    92              sleep 1
    93          else
    94              echo "jujud stopped"
    95              stopped=1
    96              break
    97          fi
    98      done
    99  fi
   100  if [ $stopped -ne 1 ]; then
   101      # If jujud didn't stop nicely, we kill it hard here.
   102      pkill -9 jujud
   103      service juju-db stop
   104  fi
   105  rm -f /etc/init/juju*
   106  rm -f /etc/systemd/system/juju*
   107  rm -fr '/var/lib/juju' '/var/log/juju'
   108  exit 0
   109  `)
   110  		return resultStdout, "", resultErr
   111  	}
   112  	s.PatchValue(&runSSHCommand, runSSHCommandTesting)
   113  	type test struct {
   114  		stdout string
   115  		err    error
   116  		match  string
   117  	}
   118  	tests := []test{
   119  		{"", nil, ""},
   120  		{"abc", nil, ""},
   121  		{"", errors.New("oh noes"), "oh noes"},
   122  	}
   123  	for i, t := range tests {
   124  		c.Logf("test %d: %v", i, t)
   125  		resultStdout, resultErr = t.stdout, t.err
   126  		err := s.env.DestroyController("controller-uuid")
   127  		if t.match == "" {
   128  			c.Assert(err, jc.ErrorIsNil)
   129  		} else {
   130  			c.Assert(err, gc.ErrorMatches, t.match)
   131  		}
   132  	}
   133  }
   134  
   135  func (s *environSuite) TestSupportsNetworking(c *gc.C) {
   136  	_, ok := environs.SupportsNetworking(s.env)
   137  	c.Assert(ok, jc.IsFalse)
   138  }
   139  
   140  func (s *environSuite) TestConstraintsValidator(c *gc.C) {
   141  	s.PatchValue(&manual.DetectSeriesAndHardwareCharacteristics,
   142  		func(string) (instance.HardwareCharacteristics, string, error) {
   143  			amd64 := "amd64"
   144  			return instance.HardwareCharacteristics{
   145  				Arch: &amd64,
   146  			}, "", nil
   147  		},
   148  	)
   149  
   150  	validator, err := s.env.ConstraintsValidator()
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	cons := constraints.MustParse("arch=amd64 instance-type=foo tags=bar cpu-power=10 cores=2 mem=1G virt-type=kvm")
   153  	unsupported, err := validator.Validate(cons)
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	c.Assert(unsupported, jc.SameContents, []string{"cpu-power", "instance-type", "tags", "virt-type"})
   156  }
   157  
   158  func (s *environSuite) TestConstraintsValidatorInsideController(c *gc.C) {
   159  	// Patch os.Args so it appears that we're running in "jujud", and then
   160  	// patch the host arch so it looks like we're running arm64.
   161  	s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"})
   162  	s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 })
   163  
   164  	validator, err := s.env.ConstraintsValidator()
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	cons := constraints.MustParse("arch=arm64")
   167  	_, err = validator.Validate(cons)
   168  	c.Assert(err, jc.ErrorIsNil)
   169  }
   170  
   171  type controllerInstancesSuite struct {
   172  	baseEnvironSuite
   173  }
   174  
   175  var _ = gc.Suite(&controllerInstancesSuite{})
   176  
   177  func (s *controllerInstancesSuite) TestControllerInstances(c *gc.C) {
   178  	var outputResult string
   179  	var errResult error
   180  	runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) {
   181  		return outputResult, "", errResult
   182  	}
   183  	s.PatchValue(&runSSHCommand, runSSHCommandTesting)
   184  
   185  	type test struct {
   186  		output      string
   187  		err         error
   188  		expectedErr string
   189  	}
   190  	tests := []test{{
   191  		output: "",
   192  	}, {
   193  		output:      "no-agent-dir",
   194  		expectedErr: "model is not bootstrapped",
   195  	}, {
   196  		output:      "woo",
   197  		expectedErr: `unexpected output: "woo"`,
   198  	}, {
   199  		err:         errors.New("an error"),
   200  		expectedErr: "an error",
   201  	}}
   202  
   203  	for i, test := range tests {
   204  		c.Logf("test %d", i)
   205  		outputResult = test.output
   206  		errResult = test.err
   207  		instances, err := s.env.ControllerInstances("not-used")
   208  		if test.expectedErr == "" {
   209  			c.Assert(err, jc.ErrorIsNil)
   210  			c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
   211  		} else {
   212  			c.Assert(err, gc.ErrorMatches, test.expectedErr)
   213  			c.Assert(instances, gc.HasLen, 0)
   214  		}
   215  	}
   216  }
   217  
   218  func (s *controllerInstancesSuite) TestControllerInstancesStderr(c *gc.C) {
   219  	// Stderr should not affect the behaviour of ControllerInstances.
   220  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 0")
   221  	_, err := s.env.ControllerInstances("not-used")
   222  	c.Assert(err, jc.ErrorIsNil)
   223  }
   224  
   225  func (s *controllerInstancesSuite) TestControllerInstancesError(c *gc.C) {
   226  	// If the ssh execution fails, its stderr will be captured in the error message.
   227  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
   228  	_, err := s.env.ControllerInstances("not-used")
   229  	c.Assert(err, gc.ErrorMatches, "abc: .*")
   230  }
   231  
   232  func (s *controllerInstancesSuite) TestControllerInstancesInternal(c *gc.C) {
   233  	// Patch os.Args so it appears that we're running in "jujud".
   234  	s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"})
   235  	// Patch the ssh executable so that it would cause an error if we
   236  	// were to call it.
   237  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
   238  	instances, err := s.env.ControllerInstances("not-used")
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
   241  }