github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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  	"github.com/juju/errors"
     8  	"github.com/juju/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/constraints"
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/storage"
    15  	envtesting "github.com/juju/juju/environs/testing"
    16  	"github.com/juju/juju/instance"
    17  	"github.com/juju/juju/juju/arch"
    18  	coretesting "github.com/juju/juju/testing"
    19  	"github.com/juju/juju/version"
    20  )
    21  
    22  type environSuite struct {
    23  	coretesting.FakeJujuHomeSuite
    24  	env *manualEnviron
    25  }
    26  
    27  type dummyStorage struct {
    28  	storage.Storage
    29  }
    30  
    31  var _ = gc.Suite(&environSuite{})
    32  
    33  func (s *environSuite) SetUpTest(c *gc.C) {
    34  	s.FakeJujuHomeSuite.SetUpTest(c)
    35  	env, err := manualProvider{}.Open(MinimalConfig(c))
    36  	c.Assert(err, jc.ErrorIsNil)
    37  	s.env = env.(*manualEnviron)
    38  }
    39  
    40  func (s *environSuite) TestSetConfig(c *gc.C) {
    41  	err := s.env.SetConfig(MinimalConfig(c))
    42  	c.Assert(err, jc.ErrorIsNil)
    43  
    44  	testConfig := MinimalConfig(c)
    45  	testConfig, err = testConfig.Apply(map[string]interface{}{"bootstrap-host": ""})
    46  	c.Assert(err, jc.ErrorIsNil)
    47  	err = s.env.SetConfig(testConfig)
    48  	c.Assert(err, gc.ErrorMatches, "bootstrap-host must be specified")
    49  }
    50  
    51  func (s *environSuite) TestInstances(c *gc.C) {
    52  	var ids []instance.Id
    53  
    54  	instances, err := s.env.Instances(ids)
    55  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
    56  	c.Assert(instances, gc.HasLen, 0)
    57  
    58  	ids = append(ids, BootstrapInstanceId)
    59  	instances, err = s.env.Instances(ids)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	c.Assert(instances, gc.HasLen, 1)
    62  	c.Assert(instances[0], gc.NotNil)
    63  
    64  	ids = append(ids, BootstrapInstanceId)
    65  	instances, err = s.env.Instances(ids)
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	c.Assert(instances, gc.HasLen, 2)
    68  	c.Assert(instances[0], gc.NotNil)
    69  	c.Assert(instances[1], gc.NotNil)
    70  
    71  	ids = append(ids, instance.Id("invalid"))
    72  	instances, err = s.env.Instances(ids)
    73  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
    74  	c.Assert(instances, gc.HasLen, 3)
    75  	c.Assert(instances[0], gc.NotNil)
    76  	c.Assert(instances[1], gc.NotNil)
    77  	c.Assert(instances[2], gc.IsNil)
    78  
    79  	ids = []instance.Id{instance.Id("invalid")}
    80  	instances, err = s.env.Instances(ids)
    81  	c.Assert(err, gc.Equals, environs.ErrNoInstances)
    82  	c.Assert(instances, gc.HasLen, 1)
    83  	c.Assert(instances[0], gc.IsNil)
    84  }
    85  
    86  func (s *environSuite) TestDestroy(c *gc.C) {
    87  	var resultStderr string
    88  	var resultErr error
    89  	runSSHCommandTesting := func(host string, command []string, stdin string) (string, error) {
    90  		c.Assert(host, gc.Equals, "ubuntu@hostname")
    91  		c.Assert(command, gc.DeepEquals, []string{"sudo", "/bin/bash"})
    92  		c.Assert(stdin, gc.DeepEquals, `
    93  set -x
    94  pkill -6 jujud && exit
    95  stop juju-db
    96  rm -f /etc/init/juju*
    97  rm -f /etc/rsyslog.d/*juju*
    98  rm -fr '/var/lib/juju' '/var/log/juju'
    99  exit 0
   100  `)
   101  		return resultStderr, resultErr
   102  	}
   103  	s.PatchValue(&runSSHCommand, runSSHCommandTesting)
   104  	type test struct {
   105  		stderr string
   106  		err    error
   107  		match  string
   108  	}
   109  	tests := []test{
   110  		{"", nil, ""},
   111  		{"abc", nil, ""},
   112  		{"", errors.New("oh noes"), "oh noes"},
   113  	}
   114  	for i, t := range tests {
   115  		c.Logf("test %d: %v", i, t)
   116  		resultStderr, resultErr = t.stderr, t.err
   117  		err := s.env.Destroy()
   118  		if t.match == "" {
   119  			c.Assert(err, jc.ErrorIsNil)
   120  		} else {
   121  			c.Assert(err, gc.ErrorMatches, t.match)
   122  		}
   123  	}
   124  }
   125  
   126  func (s *environSuite) TestLocalStorageConfig(c *gc.C) {
   127  	c.Assert(s.env.StorageDir(), gc.Equals, "/var/lib/juju/storage")
   128  	c.Assert(s.env.cfg.storageListenAddr(), gc.Equals, ":8040")
   129  	c.Assert(s.env.StorageAddr(), gc.Equals, s.env.cfg.storageListenAddr())
   130  	c.Assert(s.env.SharedStorageAddr(), gc.Equals, "")
   131  	c.Assert(s.env.SharedStorageDir(), gc.Equals, "")
   132  }
   133  
   134  func (s *environSuite) TestSupportedArchitectures(c *gc.C) {
   135  	arches, err := s.env.SupportedArchitectures()
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	c.Assert(arches, gc.DeepEquals, arch.AllSupportedArches)
   138  }
   139  
   140  func (s *environSuite) TestSupportsNetworking(c *gc.C) {
   141  	_, ok := environs.SupportsNetworking(s.env)
   142  	c.Assert(ok, jc.IsFalse)
   143  }
   144  
   145  func (s *environSuite) TestConstraintsValidator(c *gc.C) {
   146  	validator, err := s.env.ConstraintsValidator()
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	cons := constraints.MustParse("arch=amd64 instance-type=foo tags=bar cpu-power=10 cpu-cores=2 mem=1G")
   149  	unsupported, err := validator.Validate(cons)
   150  	c.Assert(err, jc.ErrorIsNil)
   151  	c.Assert(unsupported, jc.SameContents, []string{"cpu-power", "instance-type", "tags"})
   152  }
   153  
   154  type bootstrapSuite struct {
   155  	coretesting.FakeJujuHomeSuite
   156  	env *manualEnviron
   157  }
   158  
   159  var _ = gc.Suite(&bootstrapSuite{})
   160  
   161  func (s *bootstrapSuite) SetUpTest(c *gc.C) {
   162  	s.FakeJujuHomeSuite.SetUpTest(c)
   163  
   164  	// ensure use-sshstorage=true to mimic what happens
   165  	// in the real client: the environment is Prepared,
   166  	// at which point use-sshstorage=true.
   167  	cfg := MinimalConfig(c)
   168  	cfg, err := cfg.Apply(map[string]interface{}{
   169  		"use-sshstorage": true,
   170  	})
   171  	c.Assert(err, jc.ErrorIsNil)
   172  
   173  	env, err := manualProvider{}.Open(cfg)
   174  	c.Assert(err, jc.ErrorIsNil)
   175  	s.env = env.(*manualEnviron)
   176  }
   177  
   178  func (s *bootstrapSuite) TestBootstrapClearsUseSSHStorage(c *gc.C) {
   179  	s.PatchValue(&manualDetectSeriesAndHardwareCharacteristics, func(string) (instance.HardwareCharacteristics, string, error) {
   180  		arch := version.Current.Arch
   181  		return instance.HardwareCharacteristics{Arch: &arch}, "precise", nil
   182  	})
   183  	s.PatchValue(&manualCheckProvisioned, func(string) (bool, error) {
   184  		return false, nil
   185  	})
   186  
   187  	// use-sshstorage is initially true.
   188  	cfg := s.env.Config()
   189  	c.Assert(cfg.UnknownAttrs()["use-sshstorage"], jc.IsTrue)
   190  
   191  	_, _, _, err := s.env.Bootstrap(envtesting.BootstrapContext(c), environs.BootstrapParams{})
   192  	c.Assert(err, jc.ErrorIsNil)
   193  
   194  	// Bootstrap must set use-sshstorage to false within the environment.
   195  	cfg = s.env.Config()
   196  	c.Assert(cfg.UnknownAttrs()["use-sshstorage"], jc.IsFalse)
   197  }
   198  
   199  type stateServerInstancesSuite struct {
   200  	coretesting.FakeJujuHomeSuite
   201  	env *manualEnviron
   202  }
   203  
   204  var _ = gc.Suite(&stateServerInstancesSuite{})
   205  
   206  func (s *stateServerInstancesSuite) SetUpTest(c *gc.C) {
   207  	s.FakeJujuHomeSuite.SetUpTest(c)
   208  
   209  	// ensure use-sshstorage=true, or bootstrap-host
   210  	// verification won't happen in StateServerInstances.
   211  	cfg := MinimalConfig(c)
   212  	cfg, err := cfg.Apply(map[string]interface{}{
   213  		"use-sshstorage": true,
   214  	})
   215  	c.Assert(err, jc.ErrorIsNil)
   216  
   217  	env, err := manualProvider{}.Open(cfg)
   218  	c.Assert(err, jc.ErrorIsNil)
   219  	s.env = env.(*manualEnviron)
   220  }
   221  
   222  func (s *stateServerInstancesSuite) TestStateServerInstances(c *gc.C) {
   223  	var outputResult string
   224  	var errResult error
   225  	runSSHCommandTesting := func(host string, command []string, stdin string) (string, error) {
   226  		return outputResult, errResult
   227  	}
   228  	s.PatchValue(&runSSHCommand, runSSHCommandTesting)
   229  
   230  	type test struct {
   231  		output      string
   232  		err         error
   233  		expectedErr string
   234  	}
   235  	tests := []test{{
   236  		output: "",
   237  	}, {
   238  		output:      "no-agent-dir",
   239  		expectedErr: "environment is not bootstrapped",
   240  	}, {
   241  		output:      "woo",
   242  		expectedErr: `unexpected output: "woo"`,
   243  	}, {
   244  		err:         errors.New("an error"),
   245  		expectedErr: "an error",
   246  	}}
   247  
   248  	for i, test := range tests {
   249  		c.Logf("test %d", i)
   250  		outputResult = test.output
   251  		errResult = test.err
   252  		instances, err := s.env.StateServerInstances()
   253  		if test.expectedErr == "" {
   254  			c.Assert(err, jc.ErrorIsNil)
   255  			c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
   256  		} else {
   257  			c.Assert(err, gc.ErrorMatches, test.expectedErr)
   258  			c.Assert(instances, gc.HasLen, 0)
   259  		}
   260  	}
   261  }
   262  
   263  func (s *stateServerInstancesSuite) TestStateServerInstancesStderr(c *gc.C) {
   264  	// Stderr should not affect the behaviour of StateServerInstances.
   265  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 0")
   266  	_, err := s.env.StateServerInstances()
   267  	c.Assert(err, jc.ErrorIsNil)
   268  }
   269  
   270  func (s *stateServerInstancesSuite) TestStateServerInstancesError(c *gc.C) {
   271  	// If the ssh execution fails, its stderr will be captured in the error message.
   272  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
   273  	_, err := s.env.StateServerInstances()
   274  	c.Assert(err, gc.ErrorMatches, "abc: .*")
   275  }
   276  
   277  func (s *stateServerInstancesSuite) TestStateServerInstancesInternal(c *gc.C) {
   278  	// If use-sshstorage=false, then we're on the bootstrap host;
   279  	// verification is elided.
   280  	env, err := manualProvider{}.Open(MinimalConfig(c))
   281  	c.Assert(err, jc.ErrorIsNil)
   282  
   283  	testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
   284  	instances, err := env.StateServerInstances()
   285  	c.Assert(err, jc.ErrorIsNil)
   286  	c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
   287  }