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