launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/api/provisioner/provisioner_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner_test
     5  
     6  import (
     7  	gc "launchpad.net/gocheck"
     8  	stdtesting "testing"
     9  
    10  	"launchpad.net/juju-core/constraints"
    11  	"launchpad.net/juju-core/errors"
    12  	"launchpad.net/juju-core/instance"
    13  	"launchpad.net/juju-core/juju/testing"
    14  	"launchpad.net/juju-core/state"
    15  	"launchpad.net/juju-core/state/api"
    16  	commontesting "launchpad.net/juju-core/state/api/common/testing"
    17  	"launchpad.net/juju-core/state/api/params"
    18  	"launchpad.net/juju-core/state/api/provisioner"
    19  	statetesting "launchpad.net/juju-core/state/testing"
    20  	coretesting "launchpad.net/juju-core/testing"
    21  	jc "launchpad.net/juju-core/testing/checkers"
    22  	"launchpad.net/juju-core/tools"
    23  	"launchpad.net/juju-core/utils"
    24  	"launchpad.net/juju-core/version"
    25  )
    26  
    27  func TestAll(t *stdtesting.T) {
    28  	coretesting.MgoTestPackage(t)
    29  }
    30  
    31  type provisionerSuite struct {
    32  	testing.JujuConnSuite
    33  	*commontesting.EnvironWatcherTest
    34  
    35  	st      *api.State
    36  	machine *state.Machine
    37  
    38  	provisioner *provisioner.State
    39  }
    40  
    41  var _ = gc.Suite(&provisionerSuite{})
    42  
    43  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    44  	s.JujuConnSuite.SetUpTest(c)
    45  
    46  	var err error
    47  	s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron)
    48  	c.Assert(err, gc.IsNil)
    49  	password, err := utils.RandomPassword()
    50  	c.Assert(err, gc.IsNil)
    51  	err = s.machine.SetPassword(password)
    52  	c.Assert(err, gc.IsNil)
    53  	err = s.machine.SetProvisioned("i-manager", "fake_nonce", nil)
    54  	c.Assert(err, gc.IsNil)
    55  	s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce")
    56  	c.Assert(s.st, gc.NotNil)
    57  
    58  	// Create the provisioner API facade.
    59  	s.provisioner = s.st.Provisioner()
    60  	c.Assert(s.provisioner, gc.NotNil)
    61  
    62  	s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.BackingState, commontesting.HasSecrets)
    63  }
    64  
    65  func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) {
    66  	apiMachine, err := s.provisioner.Machine("machine-42")
    67  	c.Assert(err, gc.ErrorMatches, "machine 42 not found")
    68  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
    69  	c.Assert(apiMachine, gc.IsNil)
    70  
    71  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
    72  	c.Assert(err, gc.IsNil)
    73  	c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag())
    74  	c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id())
    75  }
    76  
    77  func (s *provisionerSuite) TestGetSetStatus(c *gc.C) {
    78  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
    79  	c.Assert(err, gc.IsNil)
    80  
    81  	status, info, err := apiMachine.Status()
    82  	c.Assert(err, gc.IsNil)
    83  	c.Assert(status, gc.Equals, params.StatusPending)
    84  	c.Assert(info, gc.Equals, "")
    85  
    86  	err = apiMachine.SetStatus(params.StatusStarted, "blah")
    87  	c.Assert(err, gc.IsNil)
    88  
    89  	status, info, err = apiMachine.Status()
    90  	c.Assert(err, gc.IsNil)
    91  	c.Assert(status, gc.Equals, params.StatusStarted)
    92  	c.Assert(info, gc.Equals, "blah")
    93  }
    94  
    95  func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) {
    96  	// Create a fresh machine to test the complete scenario.
    97  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    98  	c.Assert(err, gc.IsNil)
    99  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   100  
   101  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   102  	c.Assert(err, gc.IsNil)
   103  
   104  	err = apiMachine.Remove()
   105  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`)
   106  	err = apiMachine.EnsureDead()
   107  	c.Assert(err, gc.IsNil)
   108  
   109  	err = otherMachine.Refresh()
   110  	c.Assert(err, gc.IsNil)
   111  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   112  
   113  	err = apiMachine.EnsureDead()
   114  	c.Assert(err, gc.IsNil)
   115  	err = otherMachine.Refresh()
   116  	c.Assert(err, gc.IsNil)
   117  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   118  
   119  	err = apiMachine.Remove()
   120  	c.Assert(err, gc.IsNil)
   121  	err = otherMachine.Refresh()
   122  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   123  
   124  	err = apiMachine.EnsureDead()
   125  	c.Assert(err, gc.ErrorMatches, "machine 1 not found")
   126  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
   127  
   128  	// Now try to EnsureDead machine 0 - should fail.
   129  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   130  	c.Assert(err, gc.IsNil)
   131  	err = apiMachine.EnsureDead()
   132  	c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment")
   133  }
   134  
   135  func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) {
   136  	// Create a fresh machine to test the complete scenario.
   137  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   138  	c.Assert(err, gc.IsNil)
   139  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   140  
   141  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   142  	c.Assert(err, gc.IsNil)
   143  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   144  
   145  	err = apiMachine.EnsureDead()
   146  	c.Assert(err, gc.IsNil)
   147  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   148  
   149  	err = apiMachine.Refresh()
   150  	c.Assert(err, gc.IsNil)
   151  	c.Assert(apiMachine.Life(), gc.Equals, params.Dead)
   152  }
   153  
   154  func (s *provisionerSuite) TestSetProvisionedAndInstanceId(c *gc.C) {
   155  	// Create a fresh machine, since machine 0 is already provisioned.
   156  	notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   157  	c.Assert(err, gc.IsNil)
   158  
   159  	apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag())
   160  	c.Assert(err, gc.IsNil)
   161  
   162  	instanceId, err := apiMachine.InstanceId()
   163  	c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
   164  	c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned")
   165  	c.Assert(instanceId, gc.Equals, instance.Id(""))
   166  
   167  	hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G")
   168  	err = apiMachine.SetProvisioned("i-will", "fake_nonce", &hwChars)
   169  	c.Assert(err, gc.IsNil)
   170  
   171  	instanceId, err = apiMachine.InstanceId()
   172  	c.Assert(err, gc.IsNil)
   173  	c.Assert(instanceId, gc.Equals, instance.Id("i-will"))
   174  
   175  	// Try it again - should fail.
   176  	err = apiMachine.SetProvisioned("i-wont", "fake", nil)
   177  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
   178  
   179  	// Now try to get machine 0's instance id.
   180  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   181  	c.Assert(err, gc.IsNil)
   182  	instanceId, err = apiMachine.InstanceId()
   183  	c.Assert(err, gc.IsNil)
   184  	c.Assert(instanceId, gc.Equals, instance.Id("i-manager"))
   185  }
   186  
   187  func (s *provisionerSuite) TestSeries(c *gc.C) {
   188  	// Create a fresh machine with different series.
   189  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   190  	c.Assert(err, gc.IsNil)
   191  
   192  	apiMachine, err := s.provisioner.Machine(foobarMachine.Tag())
   193  	c.Assert(err, gc.IsNil)
   194  	series, err := apiMachine.Series()
   195  	c.Assert(err, gc.IsNil)
   196  	c.Assert(series, gc.Equals, "foobar")
   197  
   198  	// Now try machine 0.
   199  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   200  	c.Assert(err, gc.IsNil)
   201  	series, err = apiMachine.Series()
   202  	c.Assert(err, gc.IsNil)
   203  	c.Assert(series, gc.Equals, "quantal")
   204  }
   205  
   206  func (s *provisionerSuite) TestConstraints(c *gc.C) {
   207  	// Create a fresh machine with some constraints.
   208  	template := state.MachineTemplate{
   209  		Series:      "quantal",
   210  		Jobs:        []state.MachineJob{state.JobHostUnits},
   211  		Constraints: constraints.MustParse("cpu-cores=12", "mem=8G"),
   212  	}
   213  	consMachine, err := s.State.AddOneMachine(template)
   214  	c.Assert(err, gc.IsNil)
   215  
   216  	apiMachine, err := s.provisioner.Machine(consMachine.Tag())
   217  	c.Assert(err, gc.IsNil)
   218  	cons, err := apiMachine.Constraints()
   219  	c.Assert(err, gc.IsNil)
   220  	c.Assert(cons, gc.DeepEquals, template.Constraints)
   221  
   222  	// Now try machine 0.
   223  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   224  	c.Assert(err, gc.IsNil)
   225  	cons, err = apiMachine.Constraints()
   226  	c.Assert(err, gc.IsNil)
   227  	c.Assert(cons, gc.DeepEquals, constraints.Value{})
   228  }
   229  
   230  func (s *provisionerSuite) TestWatchContainers(c *gc.C) {
   231  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   232  	c.Assert(err, gc.IsNil)
   233  
   234  	// Add one LXC container.
   235  	template := state.MachineTemplate{
   236  		Series: "quantal",
   237  		Jobs:   []state.MachineJob{state.JobHostUnits},
   238  	}
   239  	container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   240  	c.Assert(err, gc.IsNil)
   241  
   242  	w, err := apiMachine.WatchContainers(instance.LXC)
   243  	c.Assert(err, gc.IsNil)
   244  	defer statetesting.AssertStop(c, w)
   245  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   246  
   247  	// Initial event.
   248  	wc.AssertChange(container.Id())
   249  
   250  	// Change something other than the containers and make sure it's
   251  	// not detected.
   252  	err = apiMachine.SetStatus(params.StatusStarted, "not really")
   253  	c.Assert(err, gc.IsNil)
   254  	wc.AssertNoChange()
   255  
   256  	// Add a KVM container and make sure it's not detected.
   257  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM)
   258  	c.Assert(err, gc.IsNil)
   259  	wc.AssertNoChange()
   260  
   261  	// Add another LXC container and make sure it's detected.
   262  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   263  	c.Assert(err, gc.IsNil)
   264  	wc.AssertChange(container.Id())
   265  
   266  	statetesting.AssertStop(c, w)
   267  	wc.AssertClosed()
   268  }
   269  
   270  func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) {
   271  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   272  	c.Assert(err, gc.IsNil)
   273  
   274  	for _, ctype := range instance.ContainerTypes {
   275  		w, err := apiMachine.WatchContainers(ctype)
   276  		c.Assert(w, gc.NotNil)
   277  		c.Assert(err, gc.IsNil)
   278  	}
   279  }
   280  
   281  func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) {
   282  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   283  	c.Assert(err, gc.IsNil)
   284  
   285  	_, err = apiMachine.WatchContainers(instance.NONE)
   286  	c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`)
   287  
   288  	_, err = apiMachine.WatchContainers("")
   289  	c.Assert(err, gc.ErrorMatches, "container type must be specified")
   290  }
   291  
   292  func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) {
   293  	w, err := s.provisioner.WatchEnvironMachines()
   294  	c.Assert(err, gc.IsNil)
   295  	defer statetesting.AssertStop(c, w)
   296  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   297  
   298  	// Initial event.
   299  	wc.AssertChange(s.machine.Id())
   300  
   301  	// Add another 2 machines make sure they are detected.
   302  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   303  	c.Assert(err, gc.IsNil)
   304  	otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
   305  	c.Assert(err, gc.IsNil)
   306  	wc.AssertChange("1", "2")
   307  
   308  	// Change the lifecycle of last machine.
   309  	err = otherMachine.EnsureDead()
   310  	c.Assert(err, gc.IsNil)
   311  	wc.AssertChange("2")
   312  
   313  	// Add a container and make sure it's not detected.
   314  	template := state.MachineTemplate{
   315  		Series: "quantal",
   316  		Jobs:   []state.MachineJob{state.JobHostUnits},
   317  	}
   318  	_, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   319  	c.Assert(err, gc.IsNil)
   320  	wc.AssertNoChange()
   321  
   322  	statetesting.AssertStop(c, w)
   323  	wc.AssertClosed()
   324  }
   325  
   326  func (s *provisionerSuite) TestStateAddresses(c *gc.C) {
   327  	err := s.machine.SetAddresses([]instance.Address{
   328  		instance.NewAddress("0.1.2.3"),
   329  	})
   330  	c.Assert(err, gc.IsNil)
   331  
   332  	stateAddresses, err := s.State.Addresses()
   333  	c.Assert(err, gc.IsNil)
   334  
   335  	addresses, err := s.provisioner.StateAddresses()
   336  	c.Assert(err, gc.IsNil)
   337  	c.Assert(addresses, gc.DeepEquals, stateAddresses)
   338  }
   339  
   340  func (s *provisionerSuite) TestAPIAddresses(c *gc.C) {
   341  	err := s.machine.SetAddresses([]instance.Address{
   342  		instance.NewAddress("0.1.2.3"),
   343  	})
   344  	c.Assert(err, gc.IsNil)
   345  
   346  	apiAddresses, err := s.State.APIAddresses()
   347  	c.Assert(err, gc.IsNil)
   348  
   349  	addresses, err := s.provisioner.APIAddresses()
   350  	c.Assert(err, gc.IsNil)
   351  	c.Assert(addresses, gc.DeepEquals, apiAddresses)
   352  }
   353  
   354  func (s *provisionerSuite) TestContainerConfig(c *gc.C) {
   355  	result, err := s.provisioner.ContainerConfig()
   356  	c.Assert(err, gc.IsNil)
   357  	c.Assert(result.ProviderType, gc.Equals, "dummy")
   358  	c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys)
   359  	c.Assert(result.SSLHostnameVerification, jc.IsTrue)
   360  	c.Assert(result.SyslogPort, gc.Equals, 2345)
   361  }
   362  
   363  func (s *provisionerSuite) TestCACert(c *gc.C) {
   364  	caCert, err := s.provisioner.CACert()
   365  	c.Assert(err, gc.IsNil)
   366  	c.Assert(caCert, gc.DeepEquals, s.State.CACert())
   367  }
   368  
   369  func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) {
   370  	tools, err := s.provisioner.Tools("42")
   371  	c.Assert(err, gc.ErrorMatches, "permission denied")
   372  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   373  	c.Assert(tools, gc.IsNil)
   374  }
   375  
   376  func (s *provisionerSuite) TestTools(c *gc.C) {
   377  	cur := version.Current
   378  	curTools := &tools.Tools{Version: cur, URL: ""}
   379  	curTools.Version.Minor++
   380  	s.machine.SetAgentVersion(cur)
   381  	// Provisioner.Tools returns the *desired* set of tools, not the
   382  	// currently running set. We want to be upgraded to cur.Version
   383  	stateTools, err := s.provisioner.Tools(s.machine.Tag())
   384  	c.Assert(err, gc.IsNil)
   385  	c.Assert(stateTools.Version, gc.Equals, cur)
   386  	c.Assert(stateTools.URL, gc.Not(gc.Equals), "")
   387  }
   388  
   389  func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) {
   390  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   391  	c.Assert(err, gc.IsNil)
   392  	err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM)
   393  	c.Assert(err, gc.IsNil)
   394  
   395  	err = s.machine.Refresh()
   396  	c.Assert(err, gc.IsNil)
   397  	containers, ok := s.machine.SupportedContainers()
   398  	c.Assert(ok, jc.IsTrue)
   399  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
   400  }
   401  
   402  func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) {
   403  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   404  	c.Assert(err, gc.IsNil)
   405  	err = apiMachine.SupportsNoContainers()
   406  	c.Assert(err, gc.IsNil)
   407  
   408  	err = s.machine.Refresh()
   409  	c.Assert(err, gc.IsNil)
   410  	containers, ok := s.machine.SupportedContainers()
   411  	c.Assert(ok, jc.IsTrue)
   412  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
   413  }