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