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