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