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