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