launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/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  	"fmt"
     8  	gc "launchpad.net/gocheck"
     9  	stdtesting "testing"
    10  
    11  	"launchpad.net/juju-core/constraints"
    12  	"launchpad.net/juju-core/errors"
    13  	"launchpad.net/juju-core/instance"
    14  	"launchpad.net/juju-core/juju/osenv"
    15  	"launchpad.net/juju-core/juju/testing"
    16  	"launchpad.net/juju-core/state"
    17  	"launchpad.net/juju-core/state/api/params"
    18  	"launchpad.net/juju-core/state/apiserver/common"
    19  	commontesting "launchpad.net/juju-core/state/apiserver/common/testing"
    20  	"launchpad.net/juju-core/state/apiserver/provisioner"
    21  	apiservertesting "launchpad.net/juju-core/state/apiserver/testing"
    22  	statetesting "launchpad.net/juju-core/state/testing"
    23  	coretesting "launchpad.net/juju-core/testing"
    24  	jc "launchpad.net/juju-core/testing/checkers"
    25  	"launchpad.net/juju-core/version"
    26  )
    27  
    28  func Test(t *stdtesting.T) {
    29  	coretesting.MgoTestPackage(t)
    30  }
    31  
    32  type provisionerSuite struct {
    33  	testing.JujuConnSuite
    34  
    35  	machines []*state.Machine
    36  
    37  	authorizer  apiservertesting.FakeAuthorizer
    38  	resources   *common.Resources
    39  	provisioner *provisioner.ProvisionerAPI
    40  }
    41  
    42  var _ = gc.Suite(&provisionerSuite{})
    43  
    44  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    45  	s.setUpTest(c, false)
    46  }
    47  
    48  func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) {
    49  	s.JujuConnSuite.SetUpTest(c)
    50  
    51  	// Reset previous machines (if any) and create 3 machines
    52  	// for the tests, plus an optional state server machine.
    53  	s.machines = nil
    54  	// Note that the specific machine ids allocated are assumed
    55  	// to be numerically consecutive from zero.
    56  	if withStateServer {
    57  		s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State))
    58  	}
    59  	for i := 0; i < 3; i++ {
    60  		machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    61  		c.Check(err, gc.IsNil)
    62  		s.machines = append(s.machines, machine)
    63  	}
    64  
    65  	// Create a FakeAuthorizer so we can check permissions,
    66  	// set up assuming we logged in as the environment manager.
    67  	s.authorizer = apiservertesting.FakeAuthorizer{
    68  		LoggedIn:       true,
    69  		EnvironManager: true,
    70  	}
    71  
    72  	// Create the resource registry separately to track invocations to
    73  	// Register.
    74  	s.resources = common.NewResources()
    75  
    76  	// Create a provisioner API for the machine.
    77  	provisionerAPI, err := provisioner.NewProvisionerAPI(
    78  		s.State,
    79  		s.resources,
    80  		s.authorizer,
    81  	)
    82  	c.Assert(err, gc.IsNil)
    83  	s.provisioner = provisionerAPI
    84  }
    85  
    86  type withoutStateServerSuite struct {
    87  	provisionerSuite
    88  	*commontesting.EnvironWatcherTest
    89  }
    90  
    91  var _ = gc.Suite(&withoutStateServerSuite{})
    92  
    93  func (s *withoutStateServerSuite) SetUpTest(c *gc.C) {
    94  	s.setUpTest(c, false)
    95  	s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets)
    96  }
    97  
    98  func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) {
    99  	anAuthorizer := s.authorizer
   100  	anAuthorizer.MachineAgent = false
   101  	anAuthorizer.EnvironManager = true
   102  	// Works with an environment manager, which is not a machine agent.
   103  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   104  	c.Assert(err, gc.IsNil)
   105  	c.Assert(aProvisioner, gc.NotNil)
   106  
   107  	// But fails with neither a machine agent or an environment manager.
   108  	anAuthorizer.EnvironManager = false
   109  	aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   110  	c.Assert(err, gc.NotNil)
   111  	c.Assert(aProvisioner, gc.IsNil)
   112  	c.Assert(err, gc.ErrorMatches, "permission denied")
   113  }
   114  
   115  func (s *withoutStateServerSuite) TestSetPasswords(c *gc.C) {
   116  	args := params.PasswordChanges{
   117  		Changes: []params.PasswordChange{
   118  			{Tag: s.machines[0].Tag(), Password: "xxx0-1234567890123457890"},
   119  			{Tag: s.machines[1].Tag(), Password: "xxx1-1234567890123457890"},
   120  			{Tag: s.machines[2].Tag(), Password: "xxx2-1234567890123457890"},
   121  			{Tag: "machine-42", Password: "foo"},
   122  			{Tag: "unit-foo-0", Password: "zzz"},
   123  			{Tag: "service-bar", Password: "abc"},
   124  		},
   125  	}
   126  	results, err := s.provisioner.SetPasswords(args)
   127  	c.Assert(err, gc.IsNil)
   128  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   129  		Results: []params.ErrorResult{
   130  			{nil},
   131  			{nil},
   132  			{nil},
   133  			{apiservertesting.NotFoundError("machine 42")},
   134  			{apiservertesting.ErrUnauthorized},
   135  			{apiservertesting.ErrUnauthorized},
   136  		},
   137  	})
   138  
   139  	// Verify the changes to both machines succeeded.
   140  	for i, machine := range s.machines {
   141  		c.Logf("trying %q password", machine.Tag())
   142  		err = machine.Refresh()
   143  		c.Assert(err, gc.IsNil)
   144  		changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i))
   145  		c.Assert(changed, jc.IsTrue)
   146  	}
   147  }
   148  
   149  func (s *withoutStateServerSuite) TestShortSetPasswords(c *gc.C) {
   150  	args := params.PasswordChanges{
   151  		Changes: []params.PasswordChange{
   152  			{Tag: s.machines[1].Tag(), Password: "xxx1"},
   153  		},
   154  	}
   155  	results, err := s.provisioner.SetPasswords(args)
   156  	c.Assert(err, gc.IsNil)
   157  	c.Assert(results.Results, gc.HasLen, 1)
   158  	c.Assert(results.Results[0].Error, gc.ErrorMatches,
   159  		"password is only 4 bytes long, and is not a valid Agent password")
   160  }
   161  
   162  func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) {
   163  	// NOTE: This and the next call serve to test the two
   164  	// different authorization schemes:
   165  	// 1. Machine agents can access their own machine and
   166  	// any container that has their own machine as parent;
   167  	// 2. Environment managers can access any machine without
   168  	// a parent.
   169  	// There's no need to repeat this test for each method,
   170  	// because the authorization logic is common.
   171  
   172  	// Login as a machine agent for machine 0.
   173  	anAuthorizer := s.authorizer
   174  	anAuthorizer.MachineAgent = true
   175  	anAuthorizer.EnvironManager = false
   176  	anAuthorizer.Tag = s.machines[0].Tag()
   177  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   178  	c.Assert(err, gc.IsNil)
   179  	c.Assert(aProvisioner, gc.NotNil)
   180  
   181  	// Make the machine dead before trying to add containers.
   182  	err = s.machines[0].EnsureDead()
   183  	c.Assert(err, gc.IsNil)
   184  
   185  	// Create some containers to work on.
   186  	template := state.MachineTemplate{
   187  		Series: "quantal",
   188  		Jobs:   []state.MachineJob{state.JobHostUnits},
   189  	}
   190  	var containers []*state.Machine
   191  	for i := 0; i < 3; i++ {
   192  		container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC)
   193  		c.Check(err, gc.IsNil)
   194  		containers = append(containers, container)
   195  	}
   196  	// Make one container dead.
   197  	err = containers[1].EnsureDead()
   198  	c.Assert(err, gc.IsNil)
   199  
   200  	args := params.Entities{Entities: []params.Entity{
   201  		{Tag: s.machines[0].Tag()},
   202  		{Tag: s.machines[1].Tag()},
   203  		{Tag: containers[0].Tag()},
   204  		{Tag: containers[1].Tag()},
   205  		{Tag: containers[2].Tag()},
   206  		{Tag: "machine-42"},
   207  		{Tag: "unit-foo-0"},
   208  		{Tag: "service-bar"},
   209  	}}
   210  	result, err := aProvisioner.Life(args)
   211  	c.Assert(err, gc.IsNil)
   212  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   213  		Results: []params.LifeResult{
   214  			{Life: "dead"},
   215  			{Error: apiservertesting.ErrUnauthorized},
   216  			{Life: "alive"},
   217  			{Life: "dead"},
   218  			{Life: "alive"},
   219  			{Error: apiservertesting.ErrUnauthorized},
   220  			{Error: apiservertesting.ErrUnauthorized},
   221  			{Error: apiservertesting.ErrUnauthorized},
   222  		},
   223  	})
   224  }
   225  
   226  func (s *withoutStateServerSuite) TestLifeAsEnvironManager(c *gc.C) {
   227  	err := s.machines[1].EnsureDead()
   228  	c.Assert(err, gc.IsNil)
   229  	err = s.machines[1].Refresh()
   230  	c.Assert(err, gc.IsNil)
   231  	c.Assert(s.machines[0].Life(), gc.Equals, state.Alive)
   232  	c.Assert(s.machines[1].Life(), gc.Equals, state.Dead)
   233  	c.Assert(s.machines[2].Life(), gc.Equals, state.Alive)
   234  
   235  	args := params.Entities{Entities: []params.Entity{
   236  		{Tag: s.machines[0].Tag()},
   237  		{Tag: s.machines[1].Tag()},
   238  		{Tag: s.machines[2].Tag()},
   239  		{Tag: "machine-42"},
   240  		{Tag: "unit-foo-0"},
   241  		{Tag: "service-bar"},
   242  	}}
   243  	result, err := s.provisioner.Life(args)
   244  	c.Assert(err, gc.IsNil)
   245  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   246  		Results: []params.LifeResult{
   247  			{Life: "alive"},
   248  			{Life: "dead"},
   249  			{Life: "alive"},
   250  			{Error: apiservertesting.NotFoundError("machine 42")},
   251  			{Error: apiservertesting.ErrUnauthorized},
   252  			{Error: apiservertesting.ErrUnauthorized},
   253  		},
   254  	})
   255  
   256  	// Remove the subordinate and make sure it's detected.
   257  	err = s.machines[1].Remove()
   258  	c.Assert(err, gc.IsNil)
   259  	err = s.machines[1].Refresh()
   260  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   261  
   262  	result, err = s.provisioner.Life(params.Entities{
   263  		Entities: []params.Entity{
   264  			{Tag: s.machines[1].Tag()},
   265  		},
   266  	})
   267  	c.Assert(err, gc.IsNil)
   268  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   269  		Results: []params.LifeResult{
   270  			{Error: apiservertesting.NotFoundError("machine 1")},
   271  		},
   272  	})
   273  }
   274  
   275  func (s *withoutStateServerSuite) TestRemove(c *gc.C) {
   276  	err := s.machines[1].EnsureDead()
   277  	c.Assert(err, gc.IsNil)
   278  	s.assertLife(c, 0, state.Alive)
   279  	s.assertLife(c, 1, state.Dead)
   280  	s.assertLife(c, 2, state.Alive)
   281  
   282  	args := params.Entities{Entities: []params.Entity{
   283  		{Tag: s.machines[0].Tag()},
   284  		{Tag: s.machines[1].Tag()},
   285  		{Tag: s.machines[2].Tag()},
   286  		{Tag: "machine-42"},
   287  		{Tag: "unit-foo-0"},
   288  		{Tag: "service-bar"},
   289  	}}
   290  	result, err := s.provisioner.Remove(args)
   291  	c.Assert(err, gc.IsNil)
   292  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   293  		Results: []params.ErrorResult{
   294  			{&params.Error{Message: `cannot remove entity "machine-0": still alive`}},
   295  			{nil},
   296  			{&params.Error{Message: `cannot remove entity "machine-2": still alive`}},
   297  			{apiservertesting.NotFoundError("machine 42")},
   298  			{apiservertesting.ErrUnauthorized},
   299  			{apiservertesting.ErrUnauthorized},
   300  		},
   301  	})
   302  
   303  	// Verify the changes.
   304  	s.assertLife(c, 0, state.Alive)
   305  	err = s.machines[1].Refresh()
   306  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   307  	s.assertLife(c, 2, state.Alive)
   308  }
   309  
   310  func (s *withoutStateServerSuite) TestSetStatus(c *gc.C) {
   311  	err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil)
   312  	c.Assert(err, gc.IsNil)
   313  	err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil)
   314  	c.Assert(err, gc.IsNil)
   315  	err = s.machines[2].SetStatus(params.StatusError, "not really", nil)
   316  	c.Assert(err, gc.IsNil)
   317  
   318  	args := params.SetStatus{
   319  		Entities: []params.SetEntityStatus{
   320  			{Tag: s.machines[0].Tag(), Status: params.StatusError, Info: "not really"},
   321  			{Tag: s.machines[1].Tag(), Status: params.StatusStopped, Info: "foobar"},
   322  			{Tag: s.machines[2].Tag(), Status: params.StatusStarted, Info: "again"},
   323  			{Tag: "machine-42", Status: params.StatusStarted, Info: "blah"},
   324  			{Tag: "unit-foo-0", Status: params.StatusStopped, Info: "foobar"},
   325  			{Tag: "service-bar", Status: params.StatusStopped, Info: "foobar"},
   326  		}}
   327  	result, err := s.provisioner.SetStatus(args)
   328  	c.Assert(err, gc.IsNil)
   329  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   330  		Results: []params.ErrorResult{
   331  			{nil},
   332  			{nil},
   333  			{nil},
   334  			{apiservertesting.NotFoundError("machine 42")},
   335  			{apiservertesting.ErrUnauthorized},
   336  			{apiservertesting.ErrUnauthorized},
   337  		},
   338  	})
   339  
   340  	// Verify the changes.
   341  	s.assertStatus(c, 0, params.StatusError, "not really")
   342  	s.assertStatus(c, 1, params.StatusStopped, "foobar")
   343  	s.assertStatus(c, 2, params.StatusStarted, "again")
   344  }
   345  
   346  func (s *withoutStateServerSuite) TestEnsureDead(c *gc.C) {
   347  	err := s.machines[1].EnsureDead()
   348  	c.Assert(err, gc.IsNil)
   349  	s.assertLife(c, 0, state.Alive)
   350  	s.assertLife(c, 1, state.Dead)
   351  	s.assertLife(c, 2, state.Alive)
   352  
   353  	args := params.Entities{Entities: []params.Entity{
   354  		{Tag: s.machines[0].Tag()},
   355  		{Tag: s.machines[1].Tag()},
   356  		{Tag: s.machines[2].Tag()},
   357  		{Tag: "machine-42"},
   358  		{Tag: "unit-foo-0"},
   359  		{Tag: "service-bar"},
   360  	}}
   361  	result, err := s.provisioner.EnsureDead(args)
   362  	c.Assert(err, gc.IsNil)
   363  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   364  		Results: []params.ErrorResult{
   365  			{nil},
   366  			{nil},
   367  			{nil},
   368  			{apiservertesting.NotFoundError("machine 42")},
   369  			{apiservertesting.ErrUnauthorized},
   370  			{apiservertesting.ErrUnauthorized},
   371  		},
   372  	})
   373  
   374  	// Verify the changes.
   375  	s.assertLife(c, 0, state.Dead)
   376  	s.assertLife(c, 1, state.Dead)
   377  	s.assertLife(c, 2, state.Dead)
   378  }
   379  
   380  func (s *withoutStateServerSuite) assertLife(c *gc.C, index int, expectLife state.Life) {
   381  	err := s.machines[index].Refresh()
   382  	c.Assert(err, gc.IsNil)
   383  	c.Assert(s.machines[index].Life(), gc.Equals, expectLife)
   384  }
   385  
   386  func (s *withoutStateServerSuite) assertStatus(c *gc.C, index int, expectStatus params.Status, expectInfo string) {
   387  	status, info, _, err := s.machines[index].Status()
   388  	c.Assert(err, gc.IsNil)
   389  	c.Assert(status, gc.Equals, expectStatus)
   390  	c.Assert(info, gc.Equals, expectInfo)
   391  }
   392  
   393  func (s *withoutStateServerSuite) TestWatchContainers(c *gc.C) {
   394  	c.Assert(s.resources.Count(), gc.Equals, 0)
   395  
   396  	args := params.WatchContainers{Params: []params.WatchContainer{
   397  		{MachineTag: s.machines[0].Tag(), ContainerType: string(instance.LXC)},
   398  		{MachineTag: s.machines[1].Tag(), ContainerType: string(instance.KVM)},
   399  		{MachineTag: "machine-42", ContainerType: ""},
   400  		{MachineTag: "unit-foo-0", ContainerType: ""},
   401  		{MachineTag: "service-bar", ContainerType: ""},
   402  	}}
   403  	result, err := s.provisioner.WatchContainers(args)
   404  	c.Assert(err, gc.IsNil)
   405  	c.Assert(result, jc.DeepEquals, params.StringsWatchResults{
   406  		Results: []params.StringsWatchResult{
   407  			{StringsWatcherId: "1", Changes: []string{}},
   408  			{StringsWatcherId: "2", Changes: []string{}},
   409  			{Error: apiservertesting.NotFoundError("machine 42")},
   410  			{Error: apiservertesting.ErrUnauthorized},
   411  			{Error: apiservertesting.ErrUnauthorized},
   412  		},
   413  	})
   414  
   415  	// Verify the resources were registered and stop them when done.
   416  	c.Assert(s.resources.Count(), gc.Equals, 2)
   417  	m0Watcher := s.resources.Get("1")
   418  	defer statetesting.AssertStop(c, m0Watcher)
   419  	m1Watcher := s.resources.Get("2")
   420  	defer statetesting.AssertStop(c, m1Watcher)
   421  
   422  	// Check that the Watch has consumed the initial event ("returned"
   423  	// in the Watch call)
   424  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   425  	wc0.AssertNoChange()
   426  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   427  	wc1.AssertNoChange()
   428  }
   429  
   430  func (s *withoutStateServerSuite) TestWatchAllContainers(c *gc.C) {
   431  	c.Assert(s.resources.Count(), gc.Equals, 0)
   432  
   433  	args := params.WatchContainers{Params: []params.WatchContainer{
   434  		{MachineTag: s.machines[0].Tag()},
   435  		{MachineTag: s.machines[1].Tag()},
   436  		{MachineTag: "machine-42"},
   437  		{MachineTag: "unit-foo-0"},
   438  		{MachineTag: "service-bar"},
   439  	}}
   440  	result, err := s.provisioner.WatchAllContainers(args)
   441  	c.Assert(err, gc.IsNil)
   442  	c.Assert(result, gc.DeepEquals, params.StringsWatchResults{
   443  		Results: []params.StringsWatchResult{
   444  			{StringsWatcherId: "1", Changes: []string{}},
   445  			{StringsWatcherId: "2", Changes: []string{}},
   446  			{Error: apiservertesting.NotFoundError("machine 42")},
   447  			{Error: apiservertesting.ErrUnauthorized},
   448  			{Error: apiservertesting.ErrUnauthorized},
   449  		},
   450  	})
   451  
   452  	// Verify the resources were registered and stop them when done.
   453  	c.Assert(s.resources.Count(), gc.Equals, 2)
   454  	m0Watcher := s.resources.Get("1")
   455  	defer statetesting.AssertStop(c, m0Watcher)
   456  	m1Watcher := s.resources.Get("2")
   457  	defer statetesting.AssertStop(c, m1Watcher)
   458  
   459  	// Check that the Watch has consumed the initial event ("returned"
   460  	// in the Watch call)
   461  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   462  	wc0.AssertNoChange()
   463  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   464  	wc1.AssertNoChange()
   465  }
   466  
   467  func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) {
   468  	// Now test it with a non-environment manager and make sure
   469  	// the secret attributes are masked.
   470  	anAuthorizer := s.authorizer
   471  	anAuthorizer.MachineAgent = true
   472  	anAuthorizer.EnvironManager = false
   473  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
   474  		anAuthorizer)
   475  	c.Assert(err, gc.IsNil)
   476  	s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets)
   477  }
   478  
   479  func (s *withoutStateServerSuite) TestStatus(c *gc.C) {
   480  	err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil)
   481  	c.Assert(err, gc.IsNil)
   482  	err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil)
   483  	c.Assert(err, gc.IsNil)
   484  	err = s.machines[2].SetStatus(params.StatusError, "not really", nil)
   485  	c.Assert(err, gc.IsNil)
   486  
   487  	args := params.Entities{Entities: []params.Entity{
   488  		{Tag: s.machines[0].Tag()},
   489  		{Tag: s.machines[1].Tag()},
   490  		{Tag: s.machines[2].Tag()},
   491  		{Tag: "machine-42"},
   492  		{Tag: "unit-foo-0"},
   493  		{Tag: "service-bar"},
   494  	}}
   495  	result, err := s.provisioner.Status(args)
   496  	c.Assert(err, gc.IsNil)
   497  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   498  		Results: []params.StatusResult{
   499  			{Status: params.StatusStarted, Info: "blah"},
   500  			{Status: params.StatusStopped, Info: "foo"},
   501  			{Status: params.StatusError, Info: "not really"},
   502  			{Error: apiservertesting.NotFoundError("machine 42")},
   503  			{Error: apiservertesting.ErrUnauthorized},
   504  			{Error: apiservertesting.ErrUnauthorized},
   505  		},
   506  	})
   507  }
   508  
   509  func (s *withoutStateServerSuite) TestSeries(c *gc.C) {
   510  	// Add a machine with different series.
   511  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   512  	c.Assert(err, gc.IsNil)
   513  
   514  	args := params.Entities{Entities: []params.Entity{
   515  		{Tag: s.machines[0].Tag()},
   516  		{Tag: foobarMachine.Tag()},
   517  		{Tag: s.machines[2].Tag()},
   518  		{Tag: "machine-42"},
   519  		{Tag: "unit-foo-0"},
   520  		{Tag: "service-bar"},
   521  	}}
   522  	result, err := s.provisioner.Series(args)
   523  	c.Assert(err, gc.IsNil)
   524  	c.Assert(result, gc.DeepEquals, params.StringResults{
   525  		Results: []params.StringResult{
   526  			{Result: s.machines[0].Series()},
   527  			{Result: foobarMachine.Series()},
   528  			{Result: s.machines[2].Series()},
   529  			{Error: apiservertesting.NotFoundError("machine 42")},
   530  			{Error: apiservertesting.ErrUnauthorized},
   531  			{Error: apiservertesting.ErrUnauthorized},
   532  		},
   533  	})
   534  }
   535  
   536  func (s *withoutStateServerSuite) TestConstraints(c *gc.C) {
   537  	// Add a machine with some constraints.
   538  	template := state.MachineTemplate{
   539  		Series:      "quantal",
   540  		Jobs:        []state.MachineJob{state.JobHostUnits},
   541  		Constraints: constraints.MustParse("cpu-cores=123", "mem=8G"),
   542  	}
   543  	consMachine, err := s.State.AddOneMachine(template)
   544  	c.Assert(err, gc.IsNil)
   545  
   546  	machine0Constraints, err := s.machines[0].Constraints()
   547  	c.Assert(err, gc.IsNil)
   548  
   549  	args := params.Entities{Entities: []params.Entity{
   550  		{Tag: s.machines[0].Tag()},
   551  		{Tag: consMachine.Tag()},
   552  		{Tag: "machine-42"},
   553  		{Tag: "unit-foo-0"},
   554  		{Tag: "service-bar"},
   555  	}}
   556  	result, err := s.provisioner.Constraints(args)
   557  	c.Assert(err, gc.IsNil)
   558  	c.Assert(result, gc.DeepEquals, params.ConstraintsResults{
   559  		Results: []params.ConstraintsResult{
   560  			{Constraints: machine0Constraints},
   561  			{Constraints: template.Constraints},
   562  			{Error: apiservertesting.NotFoundError("machine 42")},
   563  			{Error: apiservertesting.ErrUnauthorized},
   564  			{Error: apiservertesting.ErrUnauthorized},
   565  		},
   566  	})
   567  }
   568  
   569  func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) {
   570  	// Provision machine 0 first.
   571  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   572  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars)
   573  	c.Assert(err, gc.IsNil)
   574  
   575  	args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{
   576  		{Tag: s.machines[0].Tag(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil},
   577  		{Tag: s.machines[1].Tag(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars},
   578  		{Tag: s.machines[2].Tag(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil},
   579  		{Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil},
   580  		{Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil},
   581  		{Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil},
   582  	}}
   583  	result, err := s.provisioner.SetProvisioned(args)
   584  	c.Assert(err, gc.IsNil)
   585  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   586  		Results: []params.ErrorResult{
   587  			{&params.Error{
   588  				Message: `cannot set instance data for machine "0": already set`,
   589  			}},
   590  			{nil},
   591  			{nil},
   592  			{apiservertesting.NotFoundError("machine 42")},
   593  			{apiservertesting.ErrUnauthorized},
   594  			{apiservertesting.ErrUnauthorized},
   595  		},
   596  	})
   597  
   598  	// Verify machine 1 and 2 were provisioned.
   599  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
   600  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
   601  
   602  	instanceId, err := s.machines[1].InstanceId()
   603  	c.Assert(err, gc.IsNil)
   604  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
   605  	instanceId, err = s.machines[2].InstanceId()
   606  	c.Assert(err, gc.IsNil)
   607  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
   608  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
   609  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
   610  	gotHardware, err := s.machines[1].HardwareCharacteristics()
   611  	c.Assert(err, gc.IsNil)
   612  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
   613  }
   614  
   615  func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) {
   616  	// Provision 2 machines first.
   617  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil)
   618  	c.Assert(err, gc.IsNil)
   619  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   620  	err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars)
   621  	c.Assert(err, gc.IsNil)
   622  
   623  	args := params.Entities{Entities: []params.Entity{
   624  		{Tag: s.machines[0].Tag()},
   625  		{Tag: s.machines[1].Tag()},
   626  		{Tag: s.machines[2].Tag()},
   627  		{Tag: "machine-42"},
   628  		{Tag: "unit-foo-0"},
   629  		{Tag: "service-bar"},
   630  	}}
   631  	result, err := s.provisioner.InstanceId(args)
   632  	c.Assert(err, gc.IsNil)
   633  	c.Assert(result, gc.DeepEquals, params.StringResults{
   634  		Results: []params.StringResult{
   635  			{Result: "i-am"},
   636  			{Result: "i-am-not"},
   637  			{Error: apiservertesting.NotProvisionedError("2")},
   638  			{Error: apiservertesting.NotFoundError("machine 42")},
   639  			{Error: apiservertesting.ErrUnauthorized},
   640  			{Error: apiservertesting.ErrUnauthorized},
   641  		},
   642  	})
   643  }
   644  
   645  func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) {
   646  	c.Assert(s.resources.Count(), gc.Equals, 0)
   647  
   648  	result, err := s.provisioner.WatchEnvironMachines()
   649  	c.Assert(err, gc.IsNil)
   650  	c.Assert(result, gc.DeepEquals, params.StringsWatchResult{
   651  		StringsWatcherId: "1",
   652  		Changes:          []string{"0", "1", "2"},
   653  	})
   654  
   655  	// Verify the resources were registered and stop them when done.
   656  	c.Assert(s.resources.Count(), gc.Equals, 1)
   657  	resource := s.resources.Get("1")
   658  	defer statetesting.AssertStop(c, resource)
   659  
   660  	// Check that the Watch has consumed the initial event ("returned"
   661  	// in the Watch call)
   662  	wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
   663  	wc.AssertNoChange()
   664  
   665  	// Make sure WatchEnvironMachines fails with a machine agent login.
   666  	anAuthorizer := s.authorizer
   667  	anAuthorizer.MachineAgent = true
   668  	anAuthorizer.EnvironManager = false
   669  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   670  	c.Assert(err, gc.IsNil)
   671  
   672  	result, err = aProvisioner.WatchEnvironMachines()
   673  	c.Assert(err, gc.ErrorMatches, "permission denied")
   674  	c.Assert(result, gc.DeepEquals, params.StringsWatchResult{})
   675  }
   676  
   677  func (s *withoutStateServerSuite) TestToolsNothing(c *gc.C) {
   678  	// Not an error to watch nothing
   679  	results, err := s.provisioner.Tools(params.Entities{})
   680  	c.Assert(err, gc.IsNil)
   681  	c.Check(results.Results, gc.HasLen, 0)
   682  }
   683  
   684  func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) {
   685  	cfg, err := s.State.EnvironConfig()
   686  	c.Assert(err, gc.IsNil)
   687  	newCfg, err := cfg.Apply(map[string]interface{}{
   688  		"http-proxy": "http://proxy.example.com:9000",
   689  	})
   690  	c.Assert(err, gc.IsNil)
   691  	err = s.State.SetEnvironConfig(newCfg, cfg)
   692  	c.Assert(err, gc.IsNil)
   693  	expectedProxy := osenv.ProxySettings{
   694  		Http: "http://proxy.example.com:9000",
   695  	}
   696  
   697  	results, err := s.provisioner.ContainerConfig()
   698  	c.Check(err, gc.IsNil)
   699  	c.Check(results.ProviderType, gc.Equals, "dummy")
   700  	c.Check(results.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys)
   701  	c.Check(results.SSLHostnameVerification, jc.IsTrue)
   702  	c.Check(results.SyslogPort, gc.Equals, 2345)
   703  	c.Check(results.Proxy, gc.DeepEquals, expectedProxy)
   704  	c.Check(results.AptProxy, gc.DeepEquals, expectedProxy)
   705  }
   706  
   707  func (s *withoutStateServerSuite) TestToolsRefusesWrongAgent(c *gc.C) {
   708  	anAuthorizer := s.authorizer
   709  	anAuthorizer.Tag = "machine-12354"
   710  	anAuthorizer.EnvironManager = false
   711  	anAuthorizer.MachineAgent = true
   712  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   713  	c.Check(err, gc.IsNil)
   714  	args := params.Entities{
   715  		Entities: []params.Entity{{Tag: s.machines[0].Tag()}},
   716  	}
   717  	results, err := aProvisioner.Tools(args)
   718  	// It is not an error to make the request, but the specific item is rejected
   719  	c.Assert(err, gc.IsNil)
   720  	c.Check(results.Results, gc.HasLen, 1)
   721  	toolResult := results.Results[0]
   722  	c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   723  }
   724  
   725  func (s *withoutStateServerSuite) TestToolsForAgent(c *gc.C) {
   726  	cur := version.Current
   727  	agent := params.Entity{Tag: s.machines[0].Tag()}
   728  
   729  	// The machine must have its existing tools set before we query for the
   730  	// next tools. This is so that we can grab Arch and Series without
   731  	// having to pass it in again
   732  	err := s.machines[0].SetAgentVersion(version.Current)
   733  	c.Assert(err, gc.IsNil)
   734  
   735  	args := params.Entities{Entities: []params.Entity{agent}}
   736  	results, err := s.provisioner.Tools(args)
   737  	c.Assert(err, gc.IsNil)
   738  	c.Check(results.Results, gc.HasLen, 1)
   739  	c.Assert(results.Results[0].Error, gc.IsNil)
   740  	agentTools := results.Results[0].Tools
   741  	c.Check(agentTools.URL, gc.Not(gc.Equals), "")
   742  	c.Check(agentTools.Version, gc.DeepEquals, cur)
   743  }
   744  
   745  func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) {
   746  	args := params.MachineContainersParams{
   747  		Params: []params.MachineContainers{
   748  			{
   749  				MachineTag:     "machine-0",
   750  				ContainerTypes: []instance.ContainerType{instance.LXC},
   751  			},
   752  			{
   753  				MachineTag:     "machine-1",
   754  				ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM},
   755  			},
   756  		},
   757  	}
   758  	results, err := s.provisioner.SetSupportedContainers(args)
   759  	c.Assert(err, gc.IsNil)
   760  	c.Assert(results.Results, gc.HasLen, 2)
   761  	for _, result := range results.Results {
   762  		c.Assert(result.Error, gc.IsNil)
   763  	}
   764  	m0, err := s.State.Machine("0")
   765  	c.Assert(err, gc.IsNil)
   766  	containers, ok := m0.SupportedContainers()
   767  	c.Assert(ok, jc.IsTrue)
   768  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC})
   769  	m1, err := s.State.Machine("1")
   770  	c.Assert(err, gc.IsNil)
   771  	containers, ok = m1.SupportedContainers()
   772  	c.Assert(ok, jc.IsTrue)
   773  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
   774  }
   775  
   776  func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) {
   777  	// Login as a machine agent for machine 0.
   778  	anAuthorizer := s.authorizer
   779  	anAuthorizer.MachineAgent = true
   780  	anAuthorizer.EnvironManager = false
   781  	anAuthorizer.Tag = s.machines[0].Tag()
   782  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   783  	c.Assert(err, gc.IsNil)
   784  	c.Assert(aProvisioner, gc.NotNil)
   785  
   786  	args := params.MachineContainersParams{
   787  		Params: []params.MachineContainers{{
   788  			MachineTag:     "machine-0",
   789  			ContainerTypes: []instance.ContainerType{instance.LXC},
   790  		}, {
   791  			MachineTag:     "machine-1",
   792  			ContainerTypes: []instance.ContainerType{instance.LXC},
   793  		}, {
   794  			MachineTag:     "machine-42",
   795  			ContainerTypes: []instance.ContainerType{instance.LXC},
   796  		},
   797  		},
   798  	}
   799  	// Only machine 0 can have it's containers updated.
   800  	results, err := aProvisioner.SetSupportedContainers(args)
   801  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   802  		Results: []params.ErrorResult{
   803  			{Error: nil},
   804  			{Error: apiservertesting.ErrUnauthorized},
   805  			{Error: apiservertesting.ErrUnauthorized},
   806  		},
   807  	})
   808  }
   809  
   810  func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) {
   811  	args := params.MachineContainersParams{
   812  		Params: []params.MachineContainers{
   813  			{
   814  				MachineTag: "machine-0",
   815  			},
   816  		},
   817  	}
   818  	results, err := s.provisioner.SetSupportedContainers(args)
   819  	c.Assert(err, gc.IsNil)
   820  	c.Assert(results.Results, gc.HasLen, 1)
   821  	c.Assert(results.Results[0].Error, gc.IsNil)
   822  	m0, err := s.State.Machine("0")
   823  	c.Assert(err, gc.IsNil)
   824  	containers, ok := m0.SupportedContainers()
   825  	c.Assert(ok, jc.IsTrue)
   826  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
   827  }
   828  
   829  var _ = gc.Suite(&withStateServerSuite{})
   830  
   831  type withStateServerSuite struct {
   832  	provisionerSuite
   833  }
   834  
   835  func (s *withStateServerSuite) SetUpTest(c *gc.C) {
   836  	s.provisionerSuite.setUpTest(c, true)
   837  }
   838  
   839  func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) {
   840  	addrs, err := s.State.APIAddresses()
   841  	c.Assert(err, gc.IsNil)
   842  
   843  	result, err := s.provisioner.APIAddresses()
   844  	c.Assert(err, gc.IsNil)
   845  	c.Assert(result, gc.DeepEquals, params.StringsResult{
   846  		Result: addrs,
   847  	})
   848  }
   849  
   850  func (s *withStateServerSuite) TestStateAddresses(c *gc.C) {
   851  	addresses, err := s.State.Addresses()
   852  	c.Assert(err, gc.IsNil)
   853  
   854  	result, err := s.provisioner.StateAddresses()
   855  	c.Assert(err, gc.IsNil)
   856  	c.Assert(result, gc.DeepEquals, params.StringsResult{
   857  		Result: addresses,
   858  	})
   859  }
   860  
   861  func (s *withStateServerSuite) TestCACert(c *gc.C) {
   862  	result := s.provisioner.CACert()
   863  	c.Assert(result, gc.DeepEquals, params.BytesResult{
   864  		Result: s.State.CACert(),
   865  	})
   866  }