launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/api/uniter/unit_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter_test
     5  
     6  import (
     7  	errgo "launchpad.net/errgo/errors"
     8  	gc "launchpad.net/gocheck"
     9  
    10  	"launchpad.net/juju-core/charm"
    11  	"launchpad.net/juju-core/errors"
    12  	"launchpad.net/juju-core/instance"
    13  	"launchpad.net/juju-core/state"
    14  	"launchpad.net/juju-core/state/api/params"
    15  	"launchpad.net/juju-core/state/api/uniter"
    16  	statetesting "launchpad.net/juju-core/state/testing"
    17  	jc "launchpad.net/juju-core/testing/checkers"
    18  )
    19  
    20  type unitSuite struct {
    21  	uniterSuite
    22  
    23  	apiUnit *uniter.Unit
    24  }
    25  
    26  var _ = gc.Suite(&unitSuite{})
    27  
    28  func (s *unitSuite) SetUpTest(c *gc.C) {
    29  	s.uniterSuite.SetUpTest(c)
    30  
    31  	var err error
    32  	s.apiUnit, err = s.uniter.Unit(s.wordpressUnit.Tag())
    33  	c.Assert(err, gc.IsNil)
    34  }
    35  
    36  func (s *unitSuite) TearDownTest(c *gc.C) {
    37  	s.uniterSuite.TearDownTest(c)
    38  }
    39  
    40  func (s *unitSuite) TestUnitAndUnitTag(c *gc.C) {
    41  	apiUnitFoo, err := s.uniter.Unit("unit-foo-42")
    42  	c.Assert(err, gc.ErrorMatches, "permission denied")
    43  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
    44  	c.Assert(apiUnitFoo, gc.IsNil)
    45  
    46  	c.Assert(s.apiUnit.Tag(), gc.Equals, "unit-wordpress-0")
    47  }
    48  
    49  func (s *unitSuite) TestSetStatus(c *gc.C) {
    50  	status, info, data, err := s.wordpressUnit.Status()
    51  	c.Assert(err, gc.IsNil)
    52  	c.Assert(status, gc.Equals, params.StatusPending)
    53  	c.Assert(info, gc.Equals, "")
    54  	c.Assert(data, gc.HasLen, 0)
    55  
    56  	err = s.apiUnit.SetStatus(params.StatusStarted, "blah", nil)
    57  	c.Assert(err, gc.IsNil)
    58  
    59  	status, info, data, err = s.wordpressUnit.Status()
    60  	c.Assert(err, gc.IsNil)
    61  	c.Assert(status, gc.Equals, params.StatusStarted)
    62  	c.Assert(info, gc.Equals, "blah")
    63  	c.Assert(data, gc.HasLen, 0)
    64  }
    65  
    66  func (s *unitSuite) TestEnsureDead(c *gc.C) {
    67  	c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
    68  
    69  	err := s.apiUnit.EnsureDead()
    70  	c.Assert(err, gc.IsNil)
    71  
    72  	err = s.wordpressUnit.Refresh()
    73  	c.Assert(err, gc.IsNil)
    74  	c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead)
    75  
    76  	err = s.apiUnit.EnsureDead()
    77  	c.Assert(err, gc.IsNil)
    78  	err = s.wordpressUnit.Refresh()
    79  	c.Assert(err, gc.IsNil)
    80  	c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead)
    81  
    82  	err = s.wordpressUnit.Remove()
    83  	c.Assert(err, gc.IsNil)
    84  	err = s.wordpressUnit.Refresh()
    85  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
    86  
    87  	err = s.apiUnit.EnsureDead()
    88  	c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`)
    89  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
    90  }
    91  
    92  func (s *unitSuite) TestDestroy(c *gc.C) {
    93  	c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
    94  
    95  	err := s.apiUnit.Destroy()
    96  	c.Assert(err, gc.IsNil)
    97  
    98  	err = s.wordpressUnit.Refresh()
    99  	c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`)
   100  }
   101  
   102  func (s *unitSuite) TestDestroyAllSubordinates(c *gc.C) {
   103  	c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
   104  
   105  	// Call without subordinates - no change.
   106  	err := s.apiUnit.DestroyAllSubordinates()
   107  	c.Assert(err, gc.IsNil)
   108  
   109  	// Add a couple of subordinates and try again.
   110  	_, _, loggingSub := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit)
   111  	_, _, monitoringSub := s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit)
   112  	c.Assert(loggingSub.Life(), gc.Equals, state.Alive)
   113  	c.Assert(monitoringSub.Life(), gc.Equals, state.Alive)
   114  
   115  	err = s.apiUnit.DestroyAllSubordinates()
   116  	c.Assert(err, gc.IsNil)
   117  
   118  	// Verify they got destroyed.
   119  	err = loggingSub.Refresh()
   120  	c.Assert(err, gc.IsNil)
   121  	c.Assert(loggingSub.Life(), gc.Equals, state.Dying)
   122  	err = monitoringSub.Refresh()
   123  	c.Assert(err, gc.IsNil)
   124  	c.Assert(monitoringSub.Life(), gc.Equals, state.Dying)
   125  }
   126  
   127  func (s *unitSuite) TestRefresh(c *gc.C) {
   128  	c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
   129  
   130  	err := s.apiUnit.EnsureDead()
   131  	c.Assert(err, gc.IsNil)
   132  	c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
   133  
   134  	err = s.apiUnit.Refresh()
   135  	c.Assert(err, gc.IsNil)
   136  	c.Assert(s.apiUnit.Life(), gc.Equals, params.Dead)
   137  }
   138  
   139  func (s *unitSuite) TestWatch(c *gc.C) {
   140  	c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
   141  
   142  	w, err := s.apiUnit.Watch()
   143  	c.Assert(err, gc.IsNil)
   144  	defer statetesting.AssertStop(c, w)
   145  	wc := statetesting.NewNotifyWatcherC(c, s.BackingState, w)
   146  
   147  	// Initial event.
   148  	wc.AssertOneChange()
   149  
   150  	// Change something other than the lifecycle and make sure it's
   151  	// not detected.
   152  	err = s.apiUnit.SetStatus(params.StatusStarted, "not really", nil)
   153  	c.Assert(err, gc.IsNil)
   154  	wc.AssertNoChange()
   155  
   156  	// Make the unit dead and check it's detected.
   157  	err = s.apiUnit.EnsureDead()
   158  	c.Assert(err, gc.IsNil)
   159  	wc.AssertOneChange()
   160  
   161  	statetesting.AssertStop(c, w)
   162  	wc.AssertClosed()
   163  }
   164  
   165  func (s *unitSuite) TestResolve(c *gc.C) {
   166  	err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks)
   167  	c.Assert(err, gc.IsNil)
   168  
   169  	mode, err := s.apiUnit.Resolved()
   170  	c.Assert(err, gc.IsNil)
   171  	c.Assert(mode, gc.Equals, params.ResolvedRetryHooks)
   172  
   173  	err = s.apiUnit.ClearResolved()
   174  	c.Assert(err, gc.IsNil)
   175  
   176  	mode, err = s.apiUnit.Resolved()
   177  	c.Assert(err, gc.IsNil)
   178  	c.Assert(mode, gc.Equals, params.ResolvedNone)
   179  }
   180  
   181  func (s *unitSuite) TestIsPrincipal(c *gc.C) {
   182  	ok, err := s.apiUnit.IsPrincipal()
   183  	c.Assert(err, gc.IsNil)
   184  	c.Assert(ok, jc.IsTrue)
   185  }
   186  
   187  func (s *unitSuite) TestHasSubordinates(c *gc.C) {
   188  	found, err := s.apiUnit.HasSubordinates()
   189  	c.Assert(err, gc.IsNil)
   190  	c.Assert(found, jc.IsFalse)
   191  
   192  	// Add a couple of subordinates and try again.
   193  	s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit)
   194  	s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit)
   195  
   196  	found, err = s.apiUnit.HasSubordinates()
   197  	c.Assert(err, gc.IsNil)
   198  	c.Assert(found, jc.IsTrue)
   199  }
   200  
   201  func (s *unitSuite) TestGetSetPublicAddress(c *gc.C) {
   202  	address, err := s.apiUnit.PublicAddress()
   203  	c.Assert(err, gc.ErrorMatches, `"unit-wordpress-0" has no public address set`)
   204  
   205  	err = s.apiUnit.SetPublicAddress("1.2.3.4")
   206  	c.Assert(err, gc.IsNil)
   207  
   208  	address, err = s.apiUnit.PublicAddress()
   209  	c.Assert(err, gc.IsNil)
   210  	c.Assert(address, gc.Equals, "1.2.3.4")
   211  }
   212  
   213  func (s *unitSuite) TestGetSetPrivateAddress(c *gc.C) {
   214  	address, err := s.apiUnit.PrivateAddress()
   215  	c.Assert(err, gc.ErrorMatches, `"unit-wordpress-0" has no private address set`)
   216  
   217  	err = s.apiUnit.SetPrivateAddress("1.2.3.4")
   218  	c.Assert(err, gc.IsNil)
   219  
   220  	address, err = s.apiUnit.PrivateAddress()
   221  	c.Assert(err, gc.IsNil)
   222  	c.Assert(address, gc.Equals, "1.2.3.4")
   223  }
   224  
   225  func (s *unitSuite) TestOpenClosePort(c *gc.C) {
   226  	ports := s.wordpressUnit.OpenedPorts()
   227  	c.Assert(ports, gc.HasLen, 0)
   228  
   229  	err := s.apiUnit.OpenPort("foo", 1234)
   230  	c.Assert(err, gc.IsNil)
   231  	err = s.apiUnit.OpenPort("bar", 4321)
   232  	c.Assert(err, gc.IsNil)
   233  
   234  	err = s.wordpressUnit.Refresh()
   235  	c.Assert(err, gc.IsNil)
   236  	ports = s.wordpressUnit.OpenedPorts()
   237  	// OpenedPorts returns a sorted slice.
   238  	c.Assert(ports, gc.DeepEquals, []instance.Port{
   239  		{Protocol: "bar", Number: 4321},
   240  		{Protocol: "foo", Number: 1234},
   241  	})
   242  
   243  	err = s.apiUnit.ClosePort("bar", 4321)
   244  	c.Assert(err, gc.IsNil)
   245  
   246  	err = s.wordpressUnit.Refresh()
   247  	c.Assert(err, gc.IsNil)
   248  	ports = s.wordpressUnit.OpenedPorts()
   249  	// OpenedPorts returns a sorted slice.
   250  	c.Assert(ports, gc.DeepEquals, []instance.Port{
   251  		{Protocol: "foo", Number: 1234},
   252  	})
   253  
   254  	err = s.apiUnit.ClosePort("foo", 1234)
   255  	c.Assert(err, gc.IsNil)
   256  
   257  	err = s.wordpressUnit.Refresh()
   258  	c.Assert(err, gc.IsNil)
   259  	ports = s.wordpressUnit.OpenedPorts()
   260  	c.Assert(ports, gc.HasLen, 0)
   261  }
   262  
   263  func (s *unitSuite) TestGetSetCharmURL(c *gc.C) {
   264  	// No charm URL set yet.
   265  	curl, ok := s.wordpressUnit.CharmURL()
   266  	c.Assert(curl, gc.IsNil)
   267  	c.Assert(ok, jc.IsFalse)
   268  
   269  	// Now check the same through the API.
   270  	_, err := s.apiUnit.CharmURL()
   271  	c.Assert(errgo.Cause(err), gc.Equals, uniter.ErrNoCharmURLSet)
   272  
   273  	err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
   274  	c.Assert(err, gc.IsNil)
   275  
   276  	curl, err = s.apiUnit.CharmURL()
   277  	c.Assert(err, gc.IsNil)
   278  	c.Assert(curl, gc.NotNil)
   279  	c.Assert(curl.String(), gc.Equals, s.wordpressCharm.String())
   280  }
   281  
   282  func (s *unitSuite) TestConfigSettings(c *gc.C) {
   283  	// Make sure ConfigSettings returns an error when
   284  	// no charm URL is set, as its state counterpart does.
   285  	settings, err := s.apiUnit.ConfigSettings()
   286  	c.Assert(err, gc.ErrorMatches, "unit charm not set")
   287  
   288  	// Now set the charm and try again.
   289  	err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
   290  	c.Assert(err, gc.IsNil)
   291  
   292  	settings, err = s.apiUnit.ConfigSettings()
   293  	c.Assert(err, gc.IsNil)
   294  	c.Assert(settings, gc.DeepEquals, charm.Settings{
   295  		"blog-title": "My Title",
   296  	})
   297  
   298  	// Update the config and check we get the changes on the next call.
   299  	err = s.wordpressService.UpdateConfigSettings(charm.Settings{
   300  		"blog-title": "superhero paparazzi",
   301  	})
   302  	c.Assert(err, gc.IsNil)
   303  
   304  	settings, err = s.apiUnit.ConfigSettings()
   305  	c.Assert(err, gc.IsNil)
   306  	c.Assert(settings, gc.DeepEquals, charm.Settings{
   307  		"blog-title": "superhero paparazzi",
   308  	})
   309  }
   310  
   311  func (s *unitSuite) TestWatchConfigSettings(c *gc.C) {
   312  	// Make sure WatchConfigSettings returns an error when
   313  	// no charm URL is set, as its state counterpart does.
   314  	w, err := s.apiUnit.WatchConfigSettings()
   315  	c.Assert(err, gc.ErrorMatches, "unit charm not set")
   316  
   317  	// Now set the charm and try again.
   318  	err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
   319  	c.Assert(err, gc.IsNil)
   320  
   321  	w, err = s.apiUnit.WatchConfigSettings()
   322  	defer statetesting.AssertStop(c, w)
   323  	wc := statetesting.NewNotifyWatcherC(c, s.BackingState, w)
   324  
   325  	// Initial event.
   326  	wc.AssertOneChange()
   327  
   328  	// Update config a couple of times, check a single event.
   329  	err = s.wordpressService.UpdateConfigSettings(charm.Settings{
   330  		"blog-title": "superhero paparazzi",
   331  	})
   332  	c.Assert(err, gc.IsNil)
   333  	err = s.wordpressService.UpdateConfigSettings(charm.Settings{
   334  		"blog-title": "sauceror central",
   335  	})
   336  	c.Assert(err, gc.IsNil)
   337  	wc.AssertOneChange()
   338  
   339  	// Non-change is not reported.
   340  	err = s.wordpressService.UpdateConfigSettings(charm.Settings{
   341  		"blog-title": "sauceror central",
   342  	})
   343  	c.Assert(err, gc.IsNil)
   344  	wc.AssertNoChange()
   345  
   346  	// NOTE: This test is not as exhaustive as the one in state,
   347  	// because the watcher is already tested there. Here we just
   348  	// ensure we get the events when we expect them and don't get
   349  	// them when they're not expected.
   350  
   351  	statetesting.AssertStop(c, w)
   352  	wc.AssertClosed()
   353  }
   354  
   355  func (s *unitSuite) TestServiceNameAndTag(c *gc.C) {
   356  	c.Assert(s.apiUnit.ServiceName(), gc.Equals, "wordpress")
   357  	c.Assert(s.apiUnit.ServiceTag(), gc.Equals, "service-wordpress")
   358  }