github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/upgrader/upgrader_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgrader_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jc "github.com/juju/testing/checkers"
     9  	gc "launchpad.net/gocheck"
    10  
    11  	envtesting "github.com/juju/juju/environs/testing"
    12  	jujutesting "github.com/juju/juju/juju/testing"
    13  	"github.com/juju/juju/state"
    14  	"github.com/juju/juju/state/api/params"
    15  	"github.com/juju/juju/state/apiserver/common"
    16  	apiservertesting "github.com/juju/juju/state/apiserver/testing"
    17  	"github.com/juju/juju/state/apiserver/upgrader"
    18  	statetesting "github.com/juju/juju/state/testing"
    19  	"github.com/juju/juju/version"
    20  )
    21  
    22  type upgraderSuite struct {
    23  	jujutesting.JujuConnSuite
    24  
    25  	// These are raw State objects. Use them for setup and assertions, but
    26  	// should never be touched by the API calls themselves
    27  	rawMachine *state.Machine
    28  	apiMachine *state.Machine
    29  	upgrader   *upgrader.UpgraderAPI
    30  	resources  *common.Resources
    31  	authorizer apiservertesting.FakeAuthorizer
    32  }
    33  
    34  var _ = gc.Suite(&upgraderSuite{})
    35  
    36  func (s *upgraderSuite) SetUpTest(c *gc.C) {
    37  	s.JujuConnSuite.SetUpTest(c)
    38  	s.resources = common.NewResources()
    39  
    40  	// Create a machine to work with
    41  	var err error
    42  	// The first machine created is the only one allowed to
    43  	// JobManageEnviron
    44  	s.apiMachine, err = s.State.AddMachine("quantal", state.JobHostUnits,
    45  		state.JobManageEnviron)
    46  	c.Assert(err, gc.IsNil)
    47  	s.rawMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
    48  	c.Assert(err, gc.IsNil)
    49  
    50  	// The default auth is as the machine agent
    51  	s.authorizer = apiservertesting.FakeAuthorizer{
    52  		Tag:          s.rawMachine.Tag(),
    53  		LoggedIn:     true,
    54  		MachineAgent: true,
    55  	}
    56  	s.upgrader, err = upgrader.NewUpgraderAPI(s.State, s.resources, s.authorizer)
    57  	c.Assert(err, gc.IsNil)
    58  }
    59  
    60  func (s *upgraderSuite) TearDownTest(c *gc.C) {
    61  	if s.resources != nil {
    62  		s.resources.StopAll()
    63  	}
    64  	s.JujuConnSuite.TearDownTest(c)
    65  }
    66  
    67  func (s *upgraderSuite) TestWatchAPIVersionNothing(c *gc.C) {
    68  	// Not an error to watch nothing
    69  	results, err := s.upgrader.WatchAPIVersion(params.Entities{})
    70  	c.Assert(err, gc.IsNil)
    71  	c.Check(results.Results, gc.HasLen, 0)
    72  }
    73  
    74  func (s *upgraderSuite) TestWatchAPIVersion(c *gc.C) {
    75  	args := params.Entities{
    76  		Entities: []params.Entity{{Tag: s.rawMachine.Tag()}},
    77  	}
    78  	results, err := s.upgrader.WatchAPIVersion(args)
    79  	c.Assert(err, gc.IsNil)
    80  	c.Check(results.Results, gc.HasLen, 1)
    81  	c.Check(results.Results[0].NotifyWatcherId, gc.Not(gc.Equals), "")
    82  	c.Check(results.Results[0].Error, gc.IsNil)
    83  	resource := s.resources.Get(results.Results[0].NotifyWatcherId)
    84  	c.Check(resource, gc.NotNil)
    85  
    86  	w := resource.(state.NotifyWatcher)
    87  	wc := statetesting.NewNotifyWatcherC(c, s.State, w)
    88  	wc.AssertNoChange()
    89  
    90  	err = statetesting.SetAgentVersion(s.State, version.MustParse("3.4.567.8"))
    91  	c.Assert(err, gc.IsNil)
    92  	wc.AssertOneChange()
    93  	statetesting.AssertStop(c, w)
    94  	wc.AssertClosed()
    95  }
    96  
    97  func (s *upgraderSuite) TestUpgraderAPIRefusesNonMachineAgent(c *gc.C) {
    98  	anAuthorizer := s.authorizer
    99  	anAuthorizer.UnitAgent = true
   100  	anAuthorizer.MachineAgent = false
   101  	anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer)
   102  	c.Check(err, gc.NotNil)
   103  	c.Check(anUpgrader, gc.IsNil)
   104  	c.Assert(err, gc.ErrorMatches, "permission denied")
   105  }
   106  
   107  func (s *upgraderSuite) TestWatchAPIVersionRefusesWrongAgent(c *gc.C) {
   108  	// We are a machine agent, but not the one we are trying to track
   109  	anAuthorizer := s.authorizer
   110  	anAuthorizer.Tag = "machine-12354"
   111  	anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer)
   112  	c.Check(err, gc.IsNil)
   113  	args := params.Entities{
   114  		Entities: []params.Entity{{Tag: s.rawMachine.Tag()}},
   115  	}
   116  	results, err := anUpgrader.WatchAPIVersion(args)
   117  	// It is not an error to make the request, but the specific item is rejected
   118  	c.Assert(err, gc.IsNil)
   119  	c.Check(results.Results, gc.HasLen, 1)
   120  	c.Check(results.Results[0].NotifyWatcherId, gc.Equals, "")
   121  	c.Assert(results.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   122  }
   123  
   124  func (s *upgraderSuite) TestToolsNothing(c *gc.C) {
   125  	// Not an error to watch nothing
   126  	results, err := s.upgrader.Tools(params.Entities{})
   127  	c.Assert(err, gc.IsNil)
   128  	c.Check(results.Results, gc.HasLen, 0)
   129  }
   130  
   131  func (s *upgraderSuite) TestToolsRefusesWrongAgent(c *gc.C) {
   132  	anAuthorizer := s.authorizer
   133  	anAuthorizer.Tag = "machine-12354"
   134  	anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer)
   135  	c.Check(err, gc.IsNil)
   136  	args := params.Entities{
   137  		Entities: []params.Entity{{Tag: s.rawMachine.Tag()}},
   138  	}
   139  	results, err := anUpgrader.Tools(args)
   140  	// It is not an error to make the request, but the specific item is rejected
   141  	c.Assert(err, gc.IsNil)
   142  	c.Check(results.Results, gc.HasLen, 1)
   143  	toolResult := results.Results[0]
   144  	c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   145  }
   146  
   147  func (s *upgraderSuite) TestToolsForAgent(c *gc.C) {
   148  	cur := version.Current
   149  	agent := params.Entity{Tag: s.rawMachine.Tag()}
   150  
   151  	// The machine must have its existing tools set before we query for the
   152  	// next tools. This is so that we can grab Arch and Series without
   153  	// having to pass it in again
   154  	err := s.rawMachine.SetAgentVersion(version.Current)
   155  	c.Assert(err, gc.IsNil)
   156  
   157  	args := params.Entities{Entities: []params.Entity{agent}}
   158  	results, err := s.upgrader.Tools(args)
   159  	c.Assert(err, gc.IsNil)
   160  	assertTools := func() {
   161  		c.Check(results.Results, gc.HasLen, 1)
   162  		c.Assert(results.Results[0].Error, gc.IsNil)
   163  		agentTools := results.Results[0].Tools
   164  		c.Check(agentTools.URL, gc.Not(gc.Equals), "")
   165  		c.Check(agentTools.Version, gc.DeepEquals, cur)
   166  	}
   167  	assertTools()
   168  	c.Check(results.Results[0].DisableSSLHostnameVerification, jc.IsFalse)
   169  
   170  	envtesting.SetSSLHostnameVerification(c, s.State, false)
   171  
   172  	results, err = s.upgrader.Tools(args)
   173  	c.Assert(err, gc.IsNil)
   174  	assertTools()
   175  	c.Check(results.Results[0].DisableSSLHostnameVerification, jc.IsTrue)
   176  }
   177  
   178  func (s *upgraderSuite) TestSetToolsNothing(c *gc.C) {
   179  	// Not an error to watch nothing
   180  	results, err := s.upgrader.SetTools(params.EntitiesVersion{})
   181  	c.Assert(err, gc.IsNil)
   182  	c.Check(results.Results, gc.HasLen, 0)
   183  }
   184  
   185  func (s *upgraderSuite) TestSetToolsRefusesWrongAgent(c *gc.C) {
   186  	anAuthorizer := s.authorizer
   187  	anAuthorizer.Tag = "machine-12354"
   188  	anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer)
   189  	c.Check(err, gc.IsNil)
   190  	args := params.EntitiesVersion{
   191  		AgentTools: []params.EntityVersion{{
   192  			Tag: s.rawMachine.Tag(),
   193  			Tools: &params.Version{
   194  				Version: version.Current,
   195  			},
   196  		}},
   197  	}
   198  
   199  	results, err := anUpgrader.SetTools(args)
   200  	c.Assert(results.Results, gc.HasLen, 1)
   201  	c.Assert(results.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   202  }
   203  
   204  func (s *upgraderSuite) TestSetTools(c *gc.C) {
   205  	cur := version.Current
   206  	_, err := s.rawMachine.AgentTools()
   207  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   208  	args := params.EntitiesVersion{
   209  		AgentTools: []params.EntityVersion{{
   210  			Tag: s.rawMachine.Tag(),
   211  			Tools: &params.Version{
   212  				Version: cur,
   213  			}},
   214  		},
   215  	}
   216  	results, err := s.upgrader.SetTools(args)
   217  	c.Assert(err, gc.IsNil)
   218  	c.Assert(results.Results, gc.HasLen, 1)
   219  	c.Assert(results.Results[0].Error, gc.IsNil)
   220  	// Check that the new value actually got set, we must Refresh because
   221  	// it was set on a different Machine object
   222  	err = s.rawMachine.Refresh()
   223  	c.Assert(err, gc.IsNil)
   224  	realTools, err := s.rawMachine.AgentTools()
   225  	c.Assert(err, gc.IsNil)
   226  	c.Check(realTools.Version.Arch, gc.Equals, cur.Arch)
   227  	c.Check(realTools.Version.Series, gc.Equals, cur.Series)
   228  	c.Check(realTools.Version.Major, gc.Equals, cur.Major)
   229  	c.Check(realTools.Version.Minor, gc.Equals, cur.Minor)
   230  	c.Check(realTools.Version.Patch, gc.Equals, cur.Patch)
   231  	c.Check(realTools.Version.Build, gc.Equals, cur.Build)
   232  	c.Check(realTools.URL, gc.Equals, "")
   233  }
   234  
   235  func (s *upgraderSuite) TestDesiredVersionNothing(c *gc.C) {
   236  	// Not an error to watch nothing
   237  	results, err := s.upgrader.DesiredVersion(params.Entities{})
   238  	c.Assert(err, gc.IsNil)
   239  	c.Check(results.Results, gc.HasLen, 0)
   240  }
   241  
   242  func (s *upgraderSuite) TestDesiredVersionRefusesWrongAgent(c *gc.C) {
   243  	anAuthorizer := s.authorizer
   244  	anAuthorizer.Tag = "machine-12354"
   245  	anUpgrader, err := upgrader.NewUpgraderAPI(s.State, s.resources, anAuthorizer)
   246  	c.Check(err, gc.IsNil)
   247  	args := params.Entities{
   248  		Entities: []params.Entity{{Tag: s.rawMachine.Tag()}},
   249  	}
   250  	results, err := anUpgrader.DesiredVersion(args)
   251  	// It is not an error to make the request, but the specific item is rejected
   252  	c.Assert(err, gc.IsNil)
   253  	c.Check(results.Results, gc.HasLen, 1)
   254  	toolResult := results.Results[0]
   255  	c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   256  }
   257  
   258  func (s *upgraderSuite) TestDesiredVersionNoticesMixedAgents(c *gc.C) {
   259  	args := params.Entities{Entities: []params.Entity{
   260  		{Tag: s.rawMachine.Tag()},
   261  		{Tag: "machine-12345"},
   262  	}}
   263  	results, err := s.upgrader.DesiredVersion(args)
   264  	c.Assert(err, gc.IsNil)
   265  	c.Check(results.Results, gc.HasLen, 2)
   266  	c.Assert(results.Results[0].Error, gc.IsNil)
   267  	agentVersion := results.Results[0].Version
   268  	c.Assert(agentVersion, gc.NotNil)
   269  	c.Check(*agentVersion, gc.DeepEquals, version.Current.Number)
   270  
   271  	c.Assert(results.Results[1].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   272  	c.Assert(results.Results[1].Version, gc.IsNil)
   273  
   274  }
   275  
   276  func (s *upgraderSuite) TestDesiredVersionForAgent(c *gc.C) {
   277  	args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag()}}}
   278  	results, err := s.upgrader.DesiredVersion(args)
   279  	c.Assert(err, gc.IsNil)
   280  	c.Check(results.Results, gc.HasLen, 1)
   281  	c.Assert(results.Results[0].Error, gc.IsNil)
   282  	agentVersion := results.Results[0].Version
   283  	c.Assert(agentVersion, gc.NotNil)
   284  	c.Check(*agentVersion, gc.DeepEquals, version.Current.Number)
   285  }
   286  
   287  func (s *upgraderSuite) bumpDesiredAgentVersion(c *gc.C) version.Number {
   288  	// In order to call SetEnvironAgentVersion we have to first SetTools on
   289  	// all the existing machines
   290  	s.apiMachine.SetAgentVersion(version.Current)
   291  	s.rawMachine.SetAgentVersion(version.Current)
   292  	newer := version.Current
   293  	newer.Patch++
   294  	err := s.State.SetEnvironAgentVersion(newer.Number)
   295  	c.Assert(err, gc.IsNil)
   296  	cfg, err := s.State.EnvironConfig()
   297  	c.Assert(err, gc.IsNil)
   298  	vers, ok := cfg.AgentVersion()
   299  	c.Assert(ok, jc.IsTrue)
   300  	c.Check(vers, gc.Equals, newer.Number)
   301  	return newer.Number
   302  }
   303  
   304  func (s *upgraderSuite) TestDesiredVersionUnrestrictedForAPIAgents(c *gc.C) {
   305  	newVersion := s.bumpDesiredAgentVersion(c)
   306  	// Grab a different Upgrader for the apiMachine
   307  	authorizer := apiservertesting.FakeAuthorizer{
   308  		Tag:          s.apiMachine.Tag(),
   309  		LoggedIn:     true,
   310  		MachineAgent: true,
   311  	}
   312  	upgraderAPI, err := upgrader.NewUpgraderAPI(s.State, s.resources, authorizer)
   313  	c.Assert(err, gc.IsNil)
   314  	args := params.Entities{Entities: []params.Entity{{Tag: s.apiMachine.Tag()}}}
   315  	results, err := upgraderAPI.DesiredVersion(args)
   316  	c.Assert(err, gc.IsNil)
   317  	c.Check(results.Results, gc.HasLen, 1)
   318  	c.Assert(results.Results[0].Error, gc.IsNil)
   319  	agentVersion := results.Results[0].Version
   320  	c.Assert(agentVersion, gc.NotNil)
   321  	c.Check(*agentVersion, gc.DeepEquals, newVersion)
   322  }
   323  
   324  func (s *upgraderSuite) TestDesiredVersionRestrictedForNonAPIAgents(c *gc.C) {
   325  	newVersion := s.bumpDesiredAgentVersion(c)
   326  	c.Assert(newVersion, gc.Not(gc.Equals), version.Current.Number)
   327  	args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag()}}}
   328  	results, err := s.upgrader.DesiredVersion(args)
   329  	c.Assert(err, gc.IsNil)
   330  	c.Check(results.Results, gc.HasLen, 1)
   331  	c.Assert(results.Results[0].Error, gc.IsNil)
   332  	agentVersion := results.Results[0].Version
   333  	c.Assert(agentVersion, gc.NotNil)
   334  	c.Check(*agentVersion, gc.DeepEquals, version.Current.Number)
   335  }