github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/state/relationunit_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/juju/errors"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/charm.v6-unstable"
    16  
    17  	"github.com/juju/juju/network"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/state/testing"
    20  	coretesting "github.com/juju/juju/testing"
    21  )
    22  
    23  type RUs []*state.RelationUnit
    24  
    25  type RelationUnitSuite struct {
    26  	ConnSuite
    27  }
    28  
    29  var _ = gc.Suite(&RelationUnitSuite{})
    30  
    31  func assertInScope(c *gc.C, ru *state.RelationUnit) {
    32  	ok, err := ru.InScope()
    33  	c.Assert(err, jc.ErrorIsNil)
    34  	c.Assert(ok, jc.IsTrue)
    35  }
    36  
    37  func assertNotInScope(c *gc.C, ru *state.RelationUnit) {
    38  	assertNotJoined(c, ru)
    39  	ok, err := ru.InScope()
    40  	c.Assert(err, jc.ErrorIsNil)
    41  	c.Assert(ok, jc.IsFalse)
    42  }
    43  
    44  func assertJoined(c *gc.C, ru *state.RelationUnit) {
    45  	assertInScope(c, ru)
    46  	ok, err := ru.Joined()
    47  	c.Assert(err, jc.ErrorIsNil)
    48  	c.Assert(ok, jc.IsTrue)
    49  }
    50  
    51  func assertNotJoined(c *gc.C, ru *state.RelationUnit) {
    52  	ok, err := ru.Joined()
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	c.Assert(ok, jc.IsFalse)
    55  }
    56  
    57  func (s *RelationUnitSuite) TestReadSettingsErrors(c *gc.C) {
    58  	riak := s.AddTestingService(c, "riak", s.AddTestingCharm(c, "riak"))
    59  	u0, err := riak.AddUnit()
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	riakEP, err := riak.Endpoint("ring")
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	rel, err := s.State.EndpointsRelation(riakEP)
    64  	c.Assert(err, jc.ErrorIsNil)
    65  	ru0, err := rel.Unit(u0)
    66  	c.Assert(err, jc.ErrorIsNil)
    67  
    68  	_, err = ru0.ReadSettings("nonsense")
    69  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "nonsense" in relation "riak:ring": "nonsense" is not a valid unit name`)
    70  	_, err = ru0.ReadSettings("unknown/0")
    71  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "unknown/0" in relation "riak:ring": application "unknown" is not a member of "riak:ring"`)
    72  	_, err = ru0.ReadSettings("riak/pressure")
    73  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/pressure" in relation "riak:ring": "riak/pressure" is not a valid unit name`)
    74  	_, err = ru0.ReadSettings("riak/1")
    75  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/1" in relation "riak:ring": settings not found`)
    76  }
    77  
    78  func (s *RelationUnitSuite) TestPeerSettings(c *gc.C) {
    79  	pr := NewPeerRelation(c, s.State)
    80  	rus := RUs{pr.ru0, pr.ru1}
    81  
    82  	// Check missing settings cannot be read by any RU.
    83  	for _, ru := range rus {
    84  		_, err := ru.ReadSettings("riak/0")
    85  		c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/0" in relation "riak:ring": settings not found`)
    86  	}
    87  
    88  	// Add settings for one RU.
    89  	assertNotInScope(c, pr.ru0)
    90  	err := pr.ru0.EnterScope(map[string]interface{}{"gene": "kelly"})
    91  	c.Assert(err, jc.ErrorIsNil)
    92  	node, err := pr.ru0.Settings()
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	node.Set("meme", "socially-awkward-penguin")
    95  	_, err = node.Write()
    96  	c.Assert(err, jc.ErrorIsNil)
    97  	normal := map[string]interface{}{
    98  		"gene": "kelly",
    99  		"meme": "socially-awkward-penguin",
   100  	}
   101  
   102  	// Check settings can be read by every RU.
   103  	assertSettings := func(u *state.Unit, expect map[string]interface{}) {
   104  		for _, ru := range rus {
   105  			m, err := ru.ReadSettings(u.Name())
   106  			c.Assert(err, jc.ErrorIsNil)
   107  			c.Assert(m, gc.DeepEquals, expect)
   108  		}
   109  	}
   110  	assertSettings(pr.u0, normal)
   111  	assertJoined(c, pr.ru0)
   112  
   113  	// Check that EnterScope when scope already entered does not touch
   114  	// settings at all.
   115  	changed := map[string]interface{}{"foo": "bar"}
   116  	err = pr.ru0.EnterScope(changed)
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	assertSettings(pr.u0, normal)
   119  	assertJoined(c, pr.ru0)
   120  
   121  	// Leave scope, check settings are still as accessible as before.
   122  	err = pr.ru0.LeaveScope()
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	assertSettings(pr.u0, normal)
   125  	assertNotInScope(c, pr.ru0)
   126  
   127  	// Re-enter scope wih changed settings, and check they completely overwrite
   128  	// the old ones.
   129  	err = pr.ru0.EnterScope(changed)
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	assertSettings(pr.u0, changed)
   132  	assertJoined(c, pr.ru0)
   133  
   134  	// Leave and re-enter with nil nettings, and check they overwrite to become
   135  	// an empty map.
   136  	err = pr.ru0.LeaveScope()
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	assertNotInScope(c, pr.ru0)
   139  	err = pr.ru0.EnterScope(nil)
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	assertSettings(pr.u0, map[string]interface{}{})
   142  	assertJoined(c, pr.ru0)
   143  
   144  	// Check that entering scope for the first time with nil settings works correctly.
   145  	assertNotInScope(c, pr.ru1)
   146  	err = pr.ru1.EnterScope(nil)
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	assertSettings(pr.u1, map[string]interface{}{})
   149  	assertJoined(c, pr.ru1)
   150  }
   151  
   152  func (s *RelationUnitSuite) TestProReqSettings(c *gc.C) {
   153  	prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeGlobal)
   154  	rus := RUs{prr.pru0, prr.pru1, prr.rru0, prr.rru1}
   155  
   156  	// Check missing settings cannot be read by any RU.
   157  	for _, ru := range rus {
   158  		_, err := ru.ReadSettings("mysql/0")
   159  		c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings not found`)
   160  	}
   161  
   162  	// Add settings for one RU.
   163  	assertNotInScope(c, prr.pru0)
   164  	err := prr.pru0.EnterScope(map[string]interface{}{"gene": "simmons"})
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	node, err := prr.pru0.Settings()
   167  	c.Assert(err, jc.ErrorIsNil)
   168  	node.Set("meme", "foul-bachelor-frog")
   169  	_, err = node.Write()
   170  	c.Assert(err, jc.ErrorIsNil)
   171  	assertJoined(c, prr.pru0)
   172  
   173  	// Check settings can be read by every RU.
   174  	for _, ru := range rus {
   175  		m, err := ru.ReadSettings("mysql/0")
   176  		c.Assert(err, jc.ErrorIsNil)
   177  		c.Assert(m["gene"], gc.Equals, "simmons")
   178  		c.Assert(m["meme"], gc.Equals, "foul-bachelor-frog")
   179  	}
   180  }
   181  
   182  func (s *RelationUnitSuite) TestContainerSettings(c *gc.C) {
   183  	prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeContainer)
   184  	rus := RUs{prr.pru0, prr.pru1, prr.rru0, prr.rru1}
   185  
   186  	// Check missing settings cannot be read by any RU.
   187  	for _, ru := range rus {
   188  		_, err := ru.ReadSettings("logging/0")
   189  		c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "logging/0" in relation "logging:info mysql:juju-info": settings not found`)
   190  	}
   191  
   192  	// Add settings for one RU.
   193  	assertNotInScope(c, prr.pru0)
   194  	err := prr.pru0.EnterScope(map[string]interface{}{"gene": "hackman"})
   195  	c.Assert(err, jc.ErrorIsNil)
   196  	node, err := prr.pru0.Settings()
   197  	c.Assert(err, jc.ErrorIsNil)
   198  	node.Set("meme", "foul-bachelor-frog")
   199  	_, err = node.Write()
   200  	c.Assert(err, jc.ErrorIsNil)
   201  	assertJoined(c, prr.pru0)
   202  
   203  	// Check settings can be read by RUs in the same container.
   204  	rus0 := RUs{prr.pru0, prr.rru0}
   205  	for _, ru := range rus0 {
   206  		m, err := ru.ReadSettings("mysql/0")
   207  		c.Assert(err, jc.ErrorIsNil)
   208  		c.Assert(m["gene"], gc.Equals, "hackman")
   209  		c.Assert(m["meme"], gc.Equals, "foul-bachelor-frog")
   210  	}
   211  
   212  	// Check settings are still inaccessible to RUs outside that container
   213  	rus1 := RUs{prr.pru1, prr.rru1}
   214  	for _, ru := range rus1 {
   215  		_, err := ru.ReadSettings("mysql/0")
   216  		c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "mysql/0" in relation "logging:info mysql:juju-info": settings not found`)
   217  	}
   218  }
   219  
   220  func (s *RelationUnitSuite) TestContainerCreateSubordinate(c *gc.C) {
   221  	psvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
   222  	rsvc := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
   223  	eps, err := s.State.InferEndpoints("mysql", "logging")
   224  	c.Assert(err, jc.ErrorIsNil)
   225  	rel, err := s.State.AddRelation(eps...)
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	punit, err := psvc.AddUnit()
   228  	c.Assert(err, jc.ErrorIsNil)
   229  	pru, err := rel.Unit(punit)
   230  	c.Assert(err, jc.ErrorIsNil)
   231  
   232  	// Check that no units of the subordinate service exist.
   233  	assertSubCount := func(expect int) []*state.Unit {
   234  		runits, err := rsvc.AllUnits()
   235  		c.Assert(err, jc.ErrorIsNil)
   236  		c.Assert(runits, gc.HasLen, expect)
   237  		return runits
   238  	}
   239  	assertSubCount(0)
   240  
   241  	// Enter principal's scope and check a subordinate was created.
   242  	assertNotInScope(c, pru)
   243  	err = pru.EnterScope(nil)
   244  	c.Assert(err, jc.ErrorIsNil)
   245  	assertSubCount(1)
   246  	assertJoined(c, pru)
   247  
   248  	// Enter principal scope again and check no more subordinates created.
   249  	err = pru.EnterScope(nil)
   250  	c.Assert(err, jc.ErrorIsNil)
   251  	assertSubCount(1)
   252  	assertJoined(c, pru)
   253  
   254  	// Leave principal scope, then re-enter, and check that still no further
   255  	// subordinates are created.
   256  	err = pru.LeaveScope()
   257  	c.Assert(err, jc.ErrorIsNil)
   258  	assertNotInScope(c, pru)
   259  	err = pru.EnterScope(nil)
   260  	c.Assert(err, jc.ErrorIsNil)
   261  	runits := assertSubCount(1)
   262  	assertJoined(c, pru)
   263  
   264  	// Set the subordinate to Dying, and enter scope again; because the scope
   265  	// is already entered, no error is returned.
   266  	runit := runits[0]
   267  	err = runit.Destroy()
   268  	c.Assert(err, jc.ErrorIsNil)
   269  	err = pru.EnterScope(nil)
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	assertJoined(c, pru)
   272  
   273  	// Leave scope, then try to enter again with the Dying subordinate.
   274  	err = pru.LeaveScope()
   275  	c.Assert(err, jc.ErrorIsNil)
   276  	assertNotInScope(c, pru)
   277  	err = pru.EnterScope(nil)
   278  	c.Assert(err, gc.Equals, state.ErrCannotEnterScopeYet)
   279  	assertNotInScope(c, pru)
   280  
   281  	// Remove the subordinate, and enter scope again; this should work, and
   282  	// create a new subordinate.
   283  	err = runit.EnsureDead()
   284  	c.Assert(err, jc.ErrorIsNil)
   285  	err = runit.Remove()
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	assertSubCount(0)
   288  	assertNotInScope(c, pru)
   289  	err = pru.EnterScope(nil)
   290  	c.Assert(err, jc.ErrorIsNil)
   291  	assertSubCount(1)
   292  	assertJoined(c, pru)
   293  }
   294  
   295  func (s *RelationUnitSuite) TestDestroyRelationWithUnitsInScope(c *gc.C) {
   296  	pr := NewPeerRelation(c, s.State)
   297  	rel := pr.ru0.Relation()
   298  
   299  	// Enter two units, and check that Destroying the service sets the
   300  	// relation to Dying (rather than removing it directly).
   301  	assertNotInScope(c, pr.ru0)
   302  	err := pr.ru0.EnterScope(map[string]interface{}{"some": "settings"})
   303  	c.Assert(err, jc.ErrorIsNil)
   304  	assertJoined(c, pr.ru0)
   305  	assertNotInScope(c, pr.ru1)
   306  	err = pr.ru1.EnterScope(nil)
   307  	c.Assert(err, jc.ErrorIsNil)
   308  	assertJoined(c, pr.ru1)
   309  	err = pr.svc.Destroy()
   310  	c.Assert(err, jc.ErrorIsNil)
   311  	err = rel.Refresh()
   312  	c.Assert(err, jc.ErrorIsNil)
   313  	c.Assert(rel.Life(), gc.Equals, state.Dying)
   314  
   315  	// Check that we can't add a new unit now.
   316  	assertNotInScope(c, pr.ru2)
   317  	err = pr.ru2.EnterScope(nil)
   318  	c.Assert(err, gc.Equals, state.ErrCannotEnterScope)
   319  	assertNotInScope(c, pr.ru2)
   320  
   321  	// Check that we created no settings for the unit we failed to add.
   322  	_, err = pr.ru0.ReadSettings("riak/2")
   323  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/2" in relation "riak:ring": settings not found`)
   324  
   325  	// ru0 leaves the scope; check that service Destroy is still a no-op.
   326  	assertJoined(c, pr.ru0)
   327  	err = pr.ru0.LeaveScope()
   328  	c.Assert(err, jc.ErrorIsNil)
   329  	assertNotInScope(c, pr.ru0)
   330  	err = pr.svc.Destroy()
   331  	c.Assert(err, jc.ErrorIsNil)
   332  
   333  	// Check that unit settings for the original unit still exist, and have
   334  	// not yet been marked for deletion.
   335  	err = s.State.Cleanup()
   336  	c.Assert(err, jc.ErrorIsNil)
   337  	assertSettings := func() {
   338  		settings, err := pr.ru1.ReadSettings("riak/0")
   339  		c.Assert(err, jc.ErrorIsNil)
   340  		c.Assert(settings, gc.DeepEquals, map[string]interface{}{"some": "settings"})
   341  	}
   342  	assertSettings()
   343  
   344  	// The final unit leaves the scope, and cleans up after itself.
   345  	assertJoined(c, pr.ru1)
   346  	err = pr.ru1.LeaveScope()
   347  	c.Assert(err, jc.ErrorIsNil)
   348  	assertNotInScope(c, pr.ru1)
   349  	err = rel.Refresh()
   350  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   351  
   352  	// The settings were not themselves actually deleted yet...
   353  	assertSettings()
   354  
   355  	// ...but they were scheduled for deletion.
   356  	err = s.State.Cleanup()
   357  	c.Assert(err, jc.ErrorIsNil)
   358  	_, err = pr.ru1.ReadSettings("riak/0")
   359  	c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/0" in relation "riak:ring": settings not found`)
   360  }
   361  
   362  func (s *RelationUnitSuite) TestAliveRelationScope(c *gc.C) {
   363  	pr := NewPeerRelation(c, s.State)
   364  	rel := pr.ru0.Relation()
   365  
   366  	// Two units enter...
   367  	assertNotInScope(c, pr.ru0)
   368  	err := pr.ru0.EnterScope(nil)
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	assertJoined(c, pr.ru0)
   371  	assertNotInScope(c, pr.ru1)
   372  	err = pr.ru1.EnterScope(nil)
   373  	c.Assert(err, jc.ErrorIsNil)
   374  	assertJoined(c, pr.ru1)
   375  
   376  	// One unit becomes Dying, then re-enters the scope; this is not an error,
   377  	// because the state is already as requested.
   378  	err = pr.u0.Destroy()
   379  	c.Assert(err, jc.ErrorIsNil)
   380  	err = pr.ru0.EnterScope(nil)
   381  	c.Assert(err, jc.ErrorIsNil)
   382  	assertJoined(c, pr.ru0)
   383  
   384  	// Two units leave...
   385  	err = pr.ru0.LeaveScope()
   386  	c.Assert(err, jc.ErrorIsNil)
   387  	assertNotInScope(c, pr.ru0)
   388  	err = pr.ru1.LeaveScope()
   389  	c.Assert(err, jc.ErrorIsNil)
   390  	assertNotInScope(c, pr.ru1)
   391  
   392  	// The relation scope is empty, but the relation is still alive...
   393  	err = rel.Refresh()
   394  	c.Assert(err, jc.ErrorIsNil)
   395  	c.Assert(rel.Life(), gc.Equals, state.Alive)
   396  
   397  	// ...and new units can still join it...
   398  	assertNotInScope(c, pr.ru2)
   399  	err = pr.ru2.EnterScope(nil)
   400  	c.Assert(err, jc.ErrorIsNil)
   401  	assertJoined(c, pr.ru2)
   402  
   403  	// ...but Dying units cannot.
   404  	err = pr.u3.Destroy()
   405  	c.Assert(err, jc.ErrorIsNil)
   406  	assertNotInScope(c, pr.ru3)
   407  	err = pr.ru3.EnterScope(nil)
   408  	c.Assert(err, gc.Equals, state.ErrCannotEnterScope)
   409  	assertNotInScope(c, pr.ru3)
   410  }
   411  
   412  func (s *StateSuite) TestWatchWatchScopeDiesOnStateClose(c *gc.C) {
   413  	testWatcherDiesWhenStateCloses(c, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter {
   414  		pr := NewPeerRelation(c, st)
   415  		w := pr.ru0.WatchScope()
   416  		<-w.Changes()
   417  		return w
   418  	})
   419  }
   420  
   421  func (s *RelationUnitSuite) TestPeerWatchScope(c *gc.C) {
   422  	pr := NewPeerRelation(c, s.State)
   423  
   424  	// Test empty initial event.
   425  	w0 := pr.ru0.WatchScope()
   426  	defer testing.AssertStop(c, w0)
   427  	s.assertScopeChange(c, w0, nil, nil)
   428  	s.assertNoScopeChange(c, w0)
   429  
   430  	// ru0 enters; check no change, but settings written.
   431  	assertNotInScope(c, pr.ru0)
   432  	err := pr.ru0.EnterScope(map[string]interface{}{"foo": "bar"})
   433  	c.Assert(err, jc.ErrorIsNil)
   434  	s.assertNoScopeChange(c, w0)
   435  	node, err := pr.ru0.Settings()
   436  	c.Assert(err, jc.ErrorIsNil)
   437  	c.Assert(node.Map(), gc.DeepEquals, map[string]interface{}{"foo": "bar"})
   438  	assertJoined(c, pr.ru0)
   439  
   440  	// ru1 enters; check change is observed.
   441  	assertNotInScope(c, pr.ru1)
   442  	err = pr.ru1.EnterScope(nil)
   443  	c.Assert(err, jc.ErrorIsNil)
   444  	s.assertScopeChange(c, w0, []string{"riak/1"}, nil)
   445  	s.assertNoScopeChange(c, w0)
   446  	assertJoined(c, pr.ru1)
   447  
   448  	// ru1 enters again, check no problems and no changes.
   449  	err = pr.ru1.EnterScope(nil)
   450  	c.Assert(err, jc.ErrorIsNil)
   451  	s.assertNoScopeChange(c, w0)
   452  	assertJoined(c, pr.ru1)
   453  
   454  	// Stop watching; ru2 enters.
   455  	testing.AssertStop(c, w0)
   456  	assertNotInScope(c, pr.ru2)
   457  	err = pr.ru2.EnterScope(nil)
   458  	c.Assert(err, jc.ErrorIsNil)
   459  	assertJoined(c, pr.ru2)
   460  
   461  	// Start watch again, check initial event.
   462  	w0 = pr.ru0.WatchScope()
   463  	defer testing.AssertStop(c, w0)
   464  	s.assertScopeChange(c, w0, []string{"riak/1", "riak/2"}, nil)
   465  	s.assertNoScopeChange(c, w0)
   466  
   467  	// ru1 leaves; check event.
   468  	assertJoined(c, pr.ru1)
   469  	err = pr.ru1.LeaveScope()
   470  	c.Assert(err, jc.ErrorIsNil)
   471  	s.assertScopeChange(c, w0, nil, []string{"riak/1"})
   472  	s.assertNoScopeChange(c, w0)
   473  	assertNotInScope(c, pr.ru1)
   474  
   475  	// ru1 leaves again; check no problems and no changes.
   476  	err = pr.ru1.LeaveScope()
   477  	c.Assert(err, jc.ErrorIsNil)
   478  	s.assertNoScopeChange(c, w0)
   479  	assertNotInScope(c, pr.ru1)
   480  }
   481  
   482  func (s *RelationUnitSuite) TestProReqWatchScope(c *gc.C) {
   483  	prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeGlobal)
   484  
   485  	// Test empty initial events for all RUs.
   486  	ws := prr.watches()
   487  	for _, w := range ws {
   488  		defer testing.AssertStop(c, w)
   489  	}
   490  	for _, w := range ws {
   491  		s.assertScopeChange(c, w, nil, nil)
   492  	}
   493  	s.assertNoScopeChange(c, ws...)
   494  
   495  	// pru0 enters; check detected only by req RUs.
   496  	assertNotInScope(c, prr.pru0)
   497  	err := prr.pru0.EnterScope(nil)
   498  	c.Assert(err, jc.ErrorIsNil)
   499  	rws := func() []*state.RelationScopeWatcher {
   500  		return []*state.RelationScopeWatcher{ws[2], ws[3]}
   501  	}
   502  	for _, w := range rws() {
   503  		s.assertScopeChange(c, w, []string{"mysql/0"}, nil)
   504  	}
   505  	s.assertNoScopeChange(c, ws...)
   506  	assertJoined(c, prr.pru0)
   507  
   508  	// req0 enters; check detected only by pro RUs.
   509  	assertNotInScope(c, prr.rru0)
   510  	err = prr.rru0.EnterScope(nil)
   511  	c.Assert(err, jc.ErrorIsNil)
   512  	pws := func() []*state.RelationScopeWatcher {
   513  		return []*state.RelationScopeWatcher{ws[0], ws[1]}
   514  	}
   515  	for _, w := range pws() {
   516  		s.assertScopeChange(c, w, []string{"wordpress/0"}, nil)
   517  	}
   518  	s.assertNoScopeChange(c, ws...)
   519  	assertJoined(c, prr.rru0)
   520  
   521  	// Stop watches; remaining RUs enter.
   522  	for _, w := range ws {
   523  		testing.AssertStop(c, w)
   524  	}
   525  	assertNotInScope(c, prr.pru1)
   526  	err = prr.pru1.EnterScope(nil)
   527  	c.Assert(err, jc.ErrorIsNil)
   528  	assertJoined(c, prr.pru1)
   529  	assertNotInScope(c, prr.rru1)
   530  	err = prr.rru1.EnterScope(nil)
   531  	c.Assert(err, jc.ErrorIsNil)
   532  	assertJoined(c, prr.rru0)
   533  
   534  	// Start new watches, check initial events.
   535  	ws = prr.watches()
   536  	for _, w := range ws {
   537  		defer testing.AssertStop(c, w)
   538  	}
   539  	for _, w := range pws() {
   540  		s.assertScopeChange(c, w, []string{"wordpress/0", "wordpress/1"}, nil)
   541  	}
   542  	for _, w := range rws() {
   543  		s.assertScopeChange(c, w, []string{"mysql/0", "mysql/1"}, nil)
   544  	}
   545  	s.assertNoScopeChange(c, ws...)
   546  
   547  	// pru0 leaves; check detected only by req RUs.
   548  	assertJoined(c, prr.pru0)
   549  	err = prr.pru0.LeaveScope()
   550  	c.Assert(err, jc.ErrorIsNil)
   551  	for _, w := range rws() {
   552  		s.assertScopeChange(c, w, nil, []string{"mysql/0"})
   553  	}
   554  	s.assertNoScopeChange(c, ws...)
   555  	assertNotInScope(c, prr.pru0)
   556  
   557  	// rru0 leaves; check detected only by pro RUs.
   558  	assertJoined(c, prr.rru0)
   559  	err = prr.rru0.LeaveScope()
   560  	c.Assert(err, jc.ErrorIsNil)
   561  	for _, w := range pws() {
   562  		s.assertScopeChange(c, w, nil, []string{"wordpress/0"})
   563  	}
   564  	s.assertNoScopeChange(c, ws...)
   565  	assertNotInScope(c, prr.rru0)
   566  }
   567  
   568  func (s *RelationUnitSuite) TestContainerWatchScope(c *gc.C) {
   569  	prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeContainer)
   570  
   571  	// Test empty initial events for all RUs.
   572  	ws := prr.watches()
   573  	for _, w := range ws {
   574  		defer testing.AssertStop(c, w)
   575  	}
   576  	for _, w := range ws {
   577  		s.assertScopeChange(c, w, nil, nil)
   578  	}
   579  	s.assertNoScopeChange(c, ws...)
   580  
   581  	// pru0 enters; check detected only by same-container req.
   582  	assertNotInScope(c, prr.pru0)
   583  	err := prr.pru0.EnterScope(nil)
   584  	c.Assert(err, jc.ErrorIsNil)
   585  	s.assertScopeChange(c, ws[2], []string{"mysql/0"}, nil)
   586  	s.assertNoScopeChange(c, ws...)
   587  	assertJoined(c, prr.pru0)
   588  
   589  	// req1 enters; check detected only by same-container pro.
   590  	assertNotInScope(c, prr.rru1)
   591  	err = prr.rru1.EnterScope(nil)
   592  	c.Assert(err, jc.ErrorIsNil)
   593  	s.assertScopeChange(c, ws[1], []string{"logging/1"}, nil)
   594  	s.assertNoScopeChange(c, ws...)
   595  	assertJoined(c, prr.rru1)
   596  
   597  	// Stop watches; remaining RUs enter scope.
   598  	for _, w := range ws {
   599  		testing.AssertStop(c, w)
   600  	}
   601  	assertNotInScope(c, prr.pru1)
   602  	err = prr.pru1.EnterScope(nil)
   603  	c.Assert(err, jc.ErrorIsNil)
   604  	assertNotInScope(c, prr.rru0)
   605  	err = prr.rru0.EnterScope(nil)
   606  	c.Assert(err, jc.ErrorIsNil)
   607  
   608  	// Start new watches, check initial events.
   609  	ws = prr.watches()
   610  	for _, w := range ws {
   611  		defer testing.AssertStop(c, w)
   612  	}
   613  	s.assertScopeChange(c, ws[0], []string{"logging/0"}, nil)
   614  	s.assertScopeChange(c, ws[1], []string{"logging/1"}, nil)
   615  	s.assertScopeChange(c, ws[2], []string{"mysql/0"}, nil)
   616  	s.assertScopeChange(c, ws[3], []string{"mysql/1"}, nil)
   617  	s.assertNoScopeChange(c, ws...)
   618  	assertJoined(c, prr.pru1)
   619  	assertJoined(c, prr.rru0)
   620  
   621  	// pru0 leaves; check detected only by same-container req.
   622  	assertJoined(c, prr.pru0)
   623  	err = prr.pru0.LeaveScope()
   624  	c.Assert(err, jc.ErrorIsNil)
   625  	s.assertScopeChange(c, ws[2], nil, []string{"mysql/0"})
   626  	s.assertNoScopeChange(c, ws...)
   627  	assertNotInScope(c, prr.pru0)
   628  
   629  	// rru0 leaves; check detected only by same-container pro.
   630  	assertJoined(c, prr.rru0)
   631  	err = prr.rru0.LeaveScope()
   632  	c.Assert(err, jc.ErrorIsNil)
   633  	s.assertScopeChange(c, ws[0], nil, []string{"logging/0"})
   634  	s.assertNoScopeChange(c, ws...)
   635  	assertNotInScope(c, prr.rru0)
   636  }
   637  
   638  func (s *RelationUnitSuite) TestCoalesceWatchScope(c *gc.C) {
   639  	pr := NewPeerRelation(c, s.State)
   640  
   641  	// Test empty initial event.
   642  	w0 := pr.ru0.WatchScope()
   643  	defer testing.AssertStop(c, w0)
   644  	s.assertScopeChange(c, w0, nil, nil)
   645  	s.assertNoScopeChange(c, w0)
   646  
   647  	// ru1 and ru2 enter; check changes observed together.
   648  	err := pr.ru1.EnterScope(nil)
   649  	c.Assert(err, jc.ErrorIsNil)
   650  	err = pr.ru2.EnterScope(nil)
   651  	c.Assert(err, jc.ErrorIsNil)
   652  
   653  	s.assertScopeChange(c, w0, []string{"riak/1", "riak/2"}, nil)
   654  	s.assertNoScopeChange(c, w0)
   655  
   656  	// ru1 leaves and re-enters; check no change observed.
   657  	err = pr.ru1.LeaveScope()
   658  	c.Assert(err, jc.ErrorIsNil)
   659  	err = pr.ru1.EnterScope(nil)
   660  	c.Assert(err, jc.ErrorIsNil)
   661  	s.assertNoScopeChange(c, w0)
   662  
   663  	// ru1 and ru2 leave; check changes observed together.
   664  	err = pr.ru1.LeaveScope()
   665  	c.Assert(err, jc.ErrorIsNil)
   666  	err = pr.ru2.LeaveScope()
   667  	c.Assert(err, jc.ErrorIsNil)
   668  	s.assertScopeChange(c, w0, nil, []string{"riak/1", "riak/2"})
   669  	s.assertNoScopeChange(c, w0)
   670  }
   671  
   672  func (s *RelationUnitSuite) TestPrepareLeaveScope(c *gc.C) {
   673  	prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeGlobal)
   674  
   675  	// Test empty initial event.
   676  	w0 := prr.pru0.WatchScope()
   677  	defer testing.AssertStop(c, w0)
   678  	s.assertScopeChange(c, w0, nil, nil)
   679  	s.assertNoScopeChange(c, w0)
   680  
   681  	// rru0 and rru1 enter; check changes.
   682  	err := prr.rru0.EnterScope(nil)
   683  	c.Assert(err, jc.ErrorIsNil)
   684  	err = prr.rru1.EnterScope(nil)
   685  	c.Assert(err, jc.ErrorIsNil)
   686  	s.assertScopeChange(c, w0, []string{"wordpress/0", "wordpress/1"}, nil)
   687  	s.assertNoScopeChange(c, w0)
   688  
   689  	// rru0 notifies that it will leave soon; it's reported as departed by the
   690  	// watcher, but InScope remains accurate.
   691  	err = prr.rru0.PrepareLeaveScope()
   692  	c.Assert(err, jc.ErrorIsNil)
   693  	s.assertScopeChange(c, w0, nil, []string{"wordpress/0"})
   694  	s.assertNoScopeChange(c, w0)
   695  	assertInScope(c, prr.rru0)
   696  	assertNotJoined(c, prr.rru0)
   697  
   698  	// rru1 leaves, and the relation is destroyed; it's not removed, because
   699  	// rru0 keeps it alive until it really leaves scope.
   700  	err = prr.rru1.LeaveScope()
   701  	c.Assert(err, jc.ErrorIsNil)
   702  	s.assertScopeChange(c, w0, nil, []string{"wordpress/1"})
   703  	s.assertNoScopeChange(c, w0)
   704  	err = prr.rel.Destroy()
   705  	c.Assert(err, jc.ErrorIsNil)
   706  	err = prr.rel.Refresh()
   707  	c.Assert(err, jc.ErrorIsNil)
   708  
   709  	// rru0 really leaves; the relation is cleaned up.
   710  	err = prr.rru0.LeaveScope()
   711  	c.Assert(err, jc.ErrorIsNil)
   712  	err = prr.rel.Destroy()
   713  	c.Assert(err, jc.ErrorIsNil)
   714  	s.assertNoScopeChange(c, w0)
   715  	err = prr.rel.Refresh()
   716  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   717  }
   718  
   719  func (s *RelationUnitSuite) assertScopeChange(c *gc.C, w *state.RelationScopeWatcher, entered, left []string) {
   720  	s.State.StartSync()
   721  	select {
   722  	case ch, ok := <-w.Changes():
   723  		c.Assert(ok, jc.IsTrue)
   724  		sort.Strings(entered)
   725  		sort.Strings(ch.Entered)
   726  		c.Assert(ch.Entered, gc.DeepEquals, entered)
   727  		sort.Strings(left)
   728  		sort.Strings(ch.Left)
   729  		c.Assert(ch.Left, gc.DeepEquals, left)
   730  	case <-time.After(coretesting.LongWait):
   731  		c.Fatalf("no change")
   732  	}
   733  }
   734  
   735  func (s *RelationUnitSuite) assertNoScopeChange(c *gc.C, ws ...*state.RelationScopeWatcher) {
   736  	s.State.StartSync()
   737  	for _, w := range ws {
   738  		select {
   739  		case ch, ok := <-w.Changes():
   740  			c.Fatalf("got unwanted change: %#v, %t", ch, ok)
   741  		case <-time.After(coretesting.ShortWait):
   742  		}
   743  	}
   744  }
   745  
   746  type PeerRelation struct {
   747  	rel                *state.Relation
   748  	svc                *state.Application
   749  	u0, u1, u2, u3     *state.Unit
   750  	ru0, ru1, ru2, ru3 *state.RelationUnit
   751  }
   752  
   753  func NewPeerRelation(c *gc.C, st *state.State) *PeerRelation {
   754  	svc := state.AddTestingService(c, st, "riak", state.AddTestingCharm(c, st, "riak"))
   755  	ep, err := svc.Endpoint("ring")
   756  	c.Assert(err, jc.ErrorIsNil)
   757  	rel, err := st.EndpointsRelation(ep)
   758  	c.Assert(err, jc.ErrorIsNil)
   759  	pr := &PeerRelation{rel: rel, svc: svc}
   760  	pr.u0, pr.ru0 = addRU(c, svc, rel, nil)
   761  	pr.u1, pr.ru1 = addRU(c, svc, rel, nil)
   762  	pr.u2, pr.ru2 = addRU(c, svc, rel, nil)
   763  	pr.u3, pr.ru3 = addRU(c, svc, rel, nil)
   764  	return pr
   765  }
   766  
   767  type ProReqRelation struct {
   768  	rel                    *state.Relation
   769  	psvc, rsvc             *state.Application
   770  	pu0, pu1, ru0, ru1     *state.Unit
   771  	pru0, pru1, rru0, rru1 *state.RelationUnit
   772  }
   773  
   774  func NewProReqRelation(c *gc.C, s *ConnSuite, scope charm.RelationScope) *ProReqRelation {
   775  	psvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
   776  	var rsvc *state.Application
   777  	if scope == charm.ScopeGlobal {
   778  		rsvc = s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   779  	} else {
   780  		rsvc = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
   781  	}
   782  	eps, err := s.State.InferEndpoints("mysql", rsvc.Name())
   783  	c.Assert(err, jc.ErrorIsNil)
   784  	rel, err := s.State.AddRelation(eps...)
   785  	c.Assert(err, jc.ErrorIsNil)
   786  	prr := &ProReqRelation{rel: rel, psvc: psvc, rsvc: rsvc}
   787  	prr.pu0, prr.pru0 = addRU(c, psvc, rel, nil)
   788  	prr.pu1, prr.pru1 = addRU(c, psvc, rel, nil)
   789  	if scope == charm.ScopeGlobal {
   790  		prr.ru0, prr.rru0 = addRU(c, rsvc, rel, nil)
   791  		prr.ru1, prr.rru1 = addRU(c, rsvc, rel, nil)
   792  	} else {
   793  		prr.ru0, prr.rru0 = addRU(c, rsvc, rel, prr.pu0)
   794  		prr.ru1, prr.rru1 = addRU(c, rsvc, rel, prr.pu1)
   795  	}
   796  	return prr
   797  }
   798  
   799  func (prr *ProReqRelation) watches() []*state.RelationScopeWatcher {
   800  	return []*state.RelationScopeWatcher{
   801  		prr.pru0.WatchScope(), prr.pru1.WatchScope(),
   802  		prr.rru0.WatchScope(), prr.rru1.WatchScope(),
   803  	}
   804  }
   805  
   806  func addRU(c *gc.C, svc *state.Application, rel *state.Relation, principal *state.Unit) (*state.Unit, *state.RelationUnit) {
   807  	// Given the service svc in the relation rel, add a unit of svc and create
   808  	// a RelationUnit with rel. If principal is supplied, svc is assumed to be
   809  	// subordinate and the unit will be created by temporarily entering the
   810  	// relation's scope as the principal.
   811  	var u *state.Unit
   812  	if principal == nil {
   813  		unit, err := svc.AddUnit()
   814  		c.Assert(err, jc.ErrorIsNil)
   815  		u = unit
   816  	} else {
   817  		origUnits, err := svc.AllUnits()
   818  		c.Assert(err, jc.ErrorIsNil)
   819  		pru, err := rel.Unit(principal)
   820  		c.Assert(err, jc.ErrorIsNil)
   821  		err = pru.EnterScope(nil) // to create the subordinate
   822  		c.Assert(err, jc.ErrorIsNil)
   823  		err = pru.LeaveScope() // to reset to initial expected state
   824  		c.Assert(err, jc.ErrorIsNil)
   825  		newUnits, err := svc.AllUnits()
   826  		c.Assert(err, jc.ErrorIsNil)
   827  		for _, unit := range newUnits {
   828  			found := false
   829  			for _, old := range origUnits {
   830  				if unit.Name() == old.Name() {
   831  					found = true
   832  					break
   833  				}
   834  			}
   835  			if !found {
   836  				u = unit
   837  				break
   838  			}
   839  		}
   840  		c.Assert(u, gc.NotNil)
   841  	}
   842  	preventUnitDestroyRemove(c, u)
   843  	ru, err := rel.Unit(u)
   844  	c.Assert(err, jc.ErrorIsNil)
   845  	return u, ru
   846  }
   847  
   848  type WatchScopeSuite struct {
   849  	ConnSuite
   850  }
   851  
   852  var _ = gc.Suite(&WatchScopeSuite{})
   853  
   854  func (s *WatchScopeSuite) TestPeer(c *gc.C) {
   855  	// Create a service and get a peer relation.
   856  	riak := s.AddTestingService(c, "riak", s.AddTestingCharm(c, "riak"))
   857  	riakEP, err := riak.Endpoint("ring")
   858  	c.Assert(err, jc.ErrorIsNil)
   859  	rels, err := riak.Relations()
   860  	c.Assert(err, jc.ErrorIsNil)
   861  	c.Assert(rels, gc.HasLen, 1)
   862  	rel := rels[0]
   863  
   864  	// Add some units to the service and set their private addresses; get
   865  	// the relevant RelationUnits.
   866  	// (Private addresses should be set by their unit agents on
   867  	// startup; this test does not include that, but Join expects
   868  	// the information to be available, and uses it to populate the
   869  	// relation settings node.)
   870  	addUnit := func(i int) *state.RelationUnit {
   871  		unit, err := riak.AddUnit()
   872  		c.Assert(err, jc.ErrorIsNil)
   873  		err = unit.AssignToNewMachine()
   874  		c.Assert(err, jc.ErrorIsNil)
   875  		mId, err := unit.AssignedMachineId()
   876  		c.Assert(err, jc.ErrorIsNil)
   877  		machine, err := s.State.Machine(mId)
   878  		c.Assert(err, jc.ErrorIsNil)
   879  		privateAddr := network.NewScopedAddress(
   880  			fmt.Sprintf("riak%d.example.com", i),
   881  			network.ScopeCloudLocal,
   882  		)
   883  		machine.SetProviderAddresses(privateAddr)
   884  		ru, err := rel.Unit(unit)
   885  		c.Assert(err, jc.ErrorIsNil)
   886  		c.Assert(ru.Endpoint(), gc.Equals, riakEP)
   887  		return ru
   888  	}
   889  	ru0 := addUnit(0)
   890  	ru1 := addUnit(1)
   891  	ru2 := addUnit(2)
   892  
   893  	// ---------- Single unit ----------
   894  
   895  	// Start watching the relation from the perspective of the first unit.
   896  	w0 := ru0.Watch()
   897  	defer testing.AssertStop(c, w0)
   898  	w0c := testing.NewRelationUnitsWatcherC(c, s.State, w0)
   899  	w0c.AssertChange(nil, nil)
   900  	w0c.AssertNoChange()
   901  
   902  	// Join the first unit to the relation, and change the settings, and
   903  	// check that nothing apparently happens.
   904  	err = ru0.EnterScope(nil)
   905  	c.Assert(err, jc.ErrorIsNil)
   906  	changeSettings(c, ru0)
   907  	w0c.AssertNoChange()
   908  
   909  	// ---------- Two units ----------
   910  
   911  	// Now join another unit to the relation...
   912  	err = ru1.EnterScope(nil)
   913  	c.Assert(err, jc.ErrorIsNil)
   914  
   915  	// ...and check that the first relation unit sees the change.
   916  	expectChanged := []string{"riak/1"}
   917  	w0c.AssertChange(expectChanged, nil)
   918  	w0c.AssertNoChange()
   919  
   920  	// Join again, check it's a no-op.
   921  	err = ru1.EnterScope(nil)
   922  	c.Assert(err, jc.ErrorIsNil)
   923  	w0c.AssertNoChange()
   924  
   925  	// Start watching the relation from the perspective of the second unit,
   926  	// and check that it sees the right state.
   927  	w1 := ru1.Watch()
   928  	defer testing.AssertStop(c, w1)
   929  	w1c := testing.NewRelationUnitsWatcherC(c, s.State, w1)
   930  	expectChanged = []string{"riak/0"}
   931  	w1c.AssertChange(expectChanged, nil)
   932  	w1c.AssertNoChange()
   933  
   934  	// ---------- Three units ----------
   935  
   936  	// Whoa, it works. Ok, check the third unit's opinion of the state.
   937  	w2 := ru2.Watch()
   938  	defer testing.AssertStop(c, w2)
   939  	w2c := testing.NewRelationUnitsWatcherC(c, s.State, w2)
   940  	expectChanged = []string{"riak/0", "riak/1"}
   941  	w2c.AssertChange(expectChanged, nil)
   942  	w2c.AssertNoChange()
   943  
   944  	// Join the third unit, and check the first and second units see it.
   945  	err = ru2.EnterScope(nil)
   946  	c.Assert(err, jc.ErrorIsNil)
   947  	expectChanged = []string{"riak/2"}
   948  	w0c.AssertChange(expectChanged, nil)
   949  	w0c.AssertNoChange()
   950  	w1c.AssertChange(expectChanged, nil)
   951  	w1c.AssertNoChange()
   952  
   953  	// Change the second unit's settings, and check that only
   954  	// the first and third see changes.
   955  	changeSettings(c, ru1)
   956  	w1c.AssertNoChange()
   957  	expectChanged = []string{"riak/1"}
   958  	w0c.AssertChange(expectChanged, nil)
   959  	w0c.AssertNoChange()
   960  	w2c.AssertChange(expectChanged, nil)
   961  	w2c.AssertNoChange()
   962  
   963  	// ---------- Two units again ----------
   964  
   965  	// Depart the second unit, and check that the first and third detect it.
   966  	err = ru1.LeaveScope()
   967  	c.Assert(err, jc.ErrorIsNil)
   968  	expectDeparted := []string{"riak/1"}
   969  	w0c.AssertChange(nil, expectDeparted)
   970  	w0c.AssertNoChange()
   971  	w2c.AssertChange(nil, expectDeparted)
   972  	w2c.AssertNoChange()
   973  
   974  	// Change its settings, and check the others don't observe anything.
   975  	changeSettings(c, ru1)
   976  	w0c.AssertNoChange()
   977  	w2c.AssertNoChange()
   978  
   979  	// Check no spurious events showed up on the second unit's watch, and check
   980  	// it closes cleanly.
   981  	w1c.AssertNoChange()
   982  	testing.AssertStop(c, w1)
   983  
   984  	// OK, we're done here. Cleanup, and error detection during same,
   985  	// will be handled by the deferred kill/stop calls. Phew.
   986  }
   987  
   988  func (s *WatchScopeSuite) TestProviderRequirerGlobal(c *gc.C) {
   989  	// Create a pair of services and a relation between them.
   990  	mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
   991  	mysqlEP, err := mysql.Endpoint("server")
   992  	c.Assert(err, jc.ErrorIsNil)
   993  	wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   994  	wordpressEP, err := wordpress.Endpoint("db")
   995  	c.Assert(err, jc.ErrorIsNil)
   996  	rel, err := s.State.AddRelation(mysqlEP, wordpressEP)
   997  	c.Assert(err, jc.ErrorIsNil)
   998  
   999  	// Add some units to the services and set their private addresses.
  1000  	addUnit := func(srv *state.Application, sub string, ep state.Endpoint) *state.RelationUnit {
  1001  		unit, err := srv.AddUnit()
  1002  		c.Assert(err, jc.ErrorIsNil)
  1003  		ru, err := rel.Unit(unit)
  1004  		c.Assert(err, jc.ErrorIsNil)
  1005  		c.Assert(ru.Endpoint(), gc.Equals, ep)
  1006  		return ru
  1007  	}
  1008  	msru0 := addUnit(mysql, "ms0", mysqlEP)
  1009  	msru1 := addUnit(mysql, "ms1", mysqlEP)
  1010  	wpru0 := addUnit(wordpress, "wp0", wordpressEP)
  1011  	wpru1 := addUnit(wordpress, "wp1", wordpressEP)
  1012  
  1013  	// ---------- Single role active ----------
  1014  
  1015  	// Watch the relation from the perspective of the first provider unit and
  1016  	// check initial event.
  1017  	msw0 := msru0.Watch()
  1018  	defer testing.AssertStop(c, msw0)
  1019  	msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0)
  1020  	msw0c.AssertChange(nil, nil)
  1021  	msw0c.AssertNoChange()
  1022  
  1023  	// Join the unit to the relation, change its settings, and check that
  1024  	// nothing apparently happens.
  1025  	err = msru0.EnterScope(nil)
  1026  	c.Assert(err, jc.ErrorIsNil)
  1027  	changeSettings(c, msru0)
  1028  	msw0c.AssertNoChange()
  1029  
  1030  	// Join the second provider unit, start its watch, and check what it thinks the
  1031  	// state of the relation is.
  1032  	err = msru1.EnterScope(nil)
  1033  	c.Assert(err, jc.ErrorIsNil)
  1034  	msw1 := msru1.Watch()
  1035  	defer testing.AssertStop(c, msw1)
  1036  	msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1)
  1037  	msw1c.AssertChange(nil, nil)
  1038  	msw1c.AssertNoChange()
  1039  
  1040  	// Change the unit's settings, and check that neither provider unit
  1041  	// observes any change.
  1042  	changeSettings(c, msru1)
  1043  	msw1c.AssertNoChange()
  1044  	msw0c.AssertNoChange()
  1045  
  1046  	// ---------- Two roles active ----------
  1047  
  1048  	// Start watches from both requirer units' perspectives, and check that
  1049  	// they see the provider units.
  1050  	expectChanged := []string{"mysql/0", "mysql/1"}
  1051  	wpw0 := wpru0.Watch()
  1052  	defer testing.AssertStop(c, wpw0)
  1053  	wpw0c := testing.NewRelationUnitsWatcherC(c, s.State, wpw0)
  1054  	wpw0c.AssertChange(expectChanged, nil)
  1055  	wpw0c.AssertNoChange()
  1056  	wpw1 := wpru1.Watch()
  1057  	defer testing.AssertStop(c, wpw1)
  1058  	wpw1c := testing.NewRelationUnitsWatcherC(c, s.State, wpw1)
  1059  	wpw1c.AssertChange(expectChanged, nil)
  1060  	wpw1c.AssertNoChange()
  1061  
  1062  	// Join the first requirer unit, and check the provider units see it.
  1063  	err = wpru0.EnterScope(nil)
  1064  	c.Assert(err, jc.ErrorIsNil)
  1065  	expectChanged = []string{"wordpress/0"}
  1066  	msw0c.AssertChange(expectChanged, nil)
  1067  	msw0c.AssertNoChange()
  1068  	msw1c.AssertChange(expectChanged, nil)
  1069  	msw1c.AssertNoChange()
  1070  
  1071  	// Join again, check no-op.
  1072  	err = wpru0.EnterScope(nil)
  1073  	c.Assert(err, jc.ErrorIsNil)
  1074  	msw0c.AssertNoChange()
  1075  	msw1c.AssertNoChange()
  1076  
  1077  	// Join the second requirer, and check the provider units see the change.
  1078  	err = wpru1.EnterScope(nil)
  1079  	c.Assert(err, jc.ErrorIsNil)
  1080  	expectChanged = []string{"wordpress/1"}
  1081  	msw0c.AssertChange(expectChanged, nil)
  1082  	msw0c.AssertNoChange()
  1083  	msw1c.AssertChange(expectChanged, nil)
  1084  	msw1c.AssertNoChange()
  1085  
  1086  	// Verify that neither requirer has observed any change to the relation.
  1087  	wpw0c.AssertNoChange()
  1088  	wpw1c.AssertNoChange()
  1089  
  1090  	// Change settings for the first requirer, check providers see it...
  1091  	changeSettings(c, wpru0)
  1092  	expectChanged = []string{"wordpress/0"}
  1093  	msw0c.AssertChange(expectChanged, nil)
  1094  	msw0c.AssertNoChange()
  1095  	msw1c.AssertChange(expectChanged, nil)
  1096  	msw1c.AssertNoChange()
  1097  
  1098  	// ...and requirers don't.
  1099  	wpw0c.AssertNoChange()
  1100  	wpw1c.AssertNoChange()
  1101  
  1102  	// Depart the second requirer and check the providers see it...
  1103  	err = wpru1.LeaveScope()
  1104  	c.Assert(err, jc.ErrorIsNil)
  1105  	expectDeparted := []string{"wordpress/1"}
  1106  	msw0c.AssertChange(nil, expectDeparted)
  1107  	msw0c.AssertNoChange()
  1108  	msw1c.AssertChange(nil, expectDeparted)
  1109  	msw1c.AssertNoChange()
  1110  
  1111  	// ...and the requirers don't.
  1112  	wpw0c.AssertNoChange()
  1113  	wpw1c.AssertNoChange()
  1114  
  1115  	// Cleanup handled by defers as before.
  1116  }
  1117  
  1118  func (s *WatchScopeSuite) TestProviderRequirerContainer(c *gc.C) {
  1119  	// Create a pair of services and a relation between them.
  1120  	mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1121  	mysqlEP, err := mysql.Endpoint("juju-info")
  1122  	c.Assert(err, jc.ErrorIsNil)
  1123  	logging := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
  1124  	loggingEP, err := logging.Endpoint("info")
  1125  	c.Assert(err, jc.ErrorIsNil)
  1126  	rel, err := s.State.AddRelation(mysqlEP, loggingEP)
  1127  	c.Assert(err, jc.ErrorIsNil)
  1128  
  1129  	// Change mysqlEP to match the endpoint that will actually be used by the relation.
  1130  	mysqlEP.Scope = charm.ScopeContainer
  1131  
  1132  	// Add some units to the services and set their private addresses.
  1133  	addUnits := func(i int) (*state.RelationUnit, *state.RelationUnit) {
  1134  		msu, err := mysql.AddUnit()
  1135  		c.Assert(err, jc.ErrorIsNil)
  1136  		msru, err := rel.Unit(msu)
  1137  		c.Assert(err, jc.ErrorIsNil)
  1138  		c.Assert(msru.Endpoint(), gc.Equals, mysqlEP)
  1139  		err = msru.EnterScope(nil)
  1140  		c.Assert(err, jc.ErrorIsNil)
  1141  		err = msru.LeaveScope()
  1142  		c.Assert(err, jc.ErrorIsNil)
  1143  		lgu, err := s.State.Unit("logging/" + strconv.Itoa(i))
  1144  		c.Assert(err, jc.ErrorIsNil)
  1145  		lgru, err := rel.Unit(lgu)
  1146  		c.Assert(err, jc.ErrorIsNil)
  1147  		c.Assert(lgru.Endpoint(), gc.Equals, loggingEP)
  1148  		return msru, lgru
  1149  	}
  1150  	msru0, lgru0 := addUnits(0)
  1151  	msru1, lgru1 := addUnits(1)
  1152  
  1153  	// ---------- Single role active ----------
  1154  
  1155  	// Start watching the relation from the perspective of the first unit, and
  1156  	// check the initial event.
  1157  	msw0 := msru0.Watch()
  1158  	defer testing.AssertStop(c, msw0)
  1159  	msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0)
  1160  	msw0c.AssertChange(nil, nil)
  1161  	msw0c.AssertNoChange()
  1162  
  1163  	// Join the unit to the relation, change its settings, and check that
  1164  	// nothing apparently happens.
  1165  	err = msru0.EnterScope(nil)
  1166  	c.Assert(err, jc.ErrorIsNil)
  1167  	changeSettings(c, msru0)
  1168  	msw0c.AssertNoChange()
  1169  
  1170  	// Watch the relation from the perspective of the second provider, and
  1171  	// check initial event.
  1172  	msw1 := msru1.Watch()
  1173  	defer testing.AssertStop(c, msw1)
  1174  	msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1)
  1175  	msw1c.AssertChange(nil, nil)
  1176  	msw1c.AssertNoChange()
  1177  
  1178  	// Join the second provider unit to the relation, and check that neither
  1179  	// watching unit observes any change.
  1180  	err = msru1.EnterScope(nil)
  1181  	c.Assert(err, jc.ErrorIsNil)
  1182  	msw1c.AssertNoChange()
  1183  	msw0c.AssertNoChange()
  1184  
  1185  	// Change the unit's settings, and check that nothing apparently happens.
  1186  	changeSettings(c, msru1)
  1187  	msw1c.AssertNoChange()
  1188  	msw0c.AssertNoChange()
  1189  
  1190  	// ---------- Two roles active ----------
  1191  
  1192  	// Start a watch from the first requirer unit's perspective, and check it
  1193  	// only sees the first provider (with which it shares a container).
  1194  	lgw0 := lgru0.Watch()
  1195  	defer testing.AssertStop(c, lgw0)
  1196  	lgw0c := testing.NewRelationUnitsWatcherC(c, s.State, lgw0)
  1197  	expectChanged := []string{"mysql/0"}
  1198  	lgw0c.AssertChange(expectChanged, nil)
  1199  	lgw0c.AssertNoChange()
  1200  
  1201  	// Join the first requirer unit, and check that only the first provider
  1202  	// observes the change.
  1203  	err = lgru0.EnterScope(nil)
  1204  	c.Assert(err, jc.ErrorIsNil)
  1205  	expectChanged = []string{"logging/0"}
  1206  	msw0c.AssertChange(expectChanged, nil)
  1207  	msw0c.AssertNoChange()
  1208  	msw1c.AssertNoChange()
  1209  	lgw0c.AssertNoChange()
  1210  
  1211  	// Watch from the second requirer's perspective, and check it only sees the
  1212  	// second provider.
  1213  	lgw1 := lgru1.Watch()
  1214  	defer testing.AssertStop(c, lgw1)
  1215  	lgw1c := testing.NewRelationUnitsWatcherC(c, s.State, lgw1)
  1216  	expectChanged = []string{"mysql/1"}
  1217  	lgw1c.AssertChange(expectChanged, nil)
  1218  	lgw1c.AssertNoChange()
  1219  
  1220  	// Join the second requirer, and check that the first provider observes it...
  1221  	err = lgru1.EnterScope(nil)
  1222  	c.Assert(err, jc.ErrorIsNil)
  1223  	expectChanged = []string{"logging/1"}
  1224  	msw1c.AssertChange(expectChanged, nil)
  1225  	msw1c.AssertNoChange()
  1226  
  1227  	// ...and that nothing else sees anything.
  1228  	msw0c.AssertNoChange()
  1229  	lgw0c.AssertNoChange()
  1230  	lgw1c.AssertNoChange()
  1231  
  1232  	// Change the second provider's settings and check that the second
  1233  	// requirer notices...
  1234  	changeSettings(c, msru1)
  1235  	expectChanged = []string{"mysql/1"}
  1236  	lgw1c.AssertChange(expectChanged, nil)
  1237  	lgw1c.AssertNoChange()
  1238  
  1239  	// ...but that nothing else does.
  1240  	msw0c.AssertNoChange()
  1241  	msw1c.AssertNoChange()
  1242  	msw0c.AssertNoChange()
  1243  
  1244  	// Finally, depart the first provider, and check that only the first
  1245  	// requirer observes any change.
  1246  	err = msru0.LeaveScope()
  1247  	c.Assert(err, jc.ErrorIsNil)
  1248  	expectDeparted := []string{"mysql/0"}
  1249  	lgw0c.AssertChange(nil, expectDeparted)
  1250  	lgw0c.AssertNoChange()
  1251  	lgw1c.AssertNoChange()
  1252  	msw0c.AssertNoChange()
  1253  	msw1c.AssertNoChange()
  1254  
  1255  	// Again, I think we're done, and can be comfortable that the appropriate
  1256  	// connections are in place.
  1257  }
  1258  
  1259  func changeSettings(c *gc.C, ru *state.RelationUnit) {
  1260  	node, err := ru.Settings()
  1261  	c.Assert(err, jc.ErrorIsNil)
  1262  	value, _ := node.Get("value")
  1263  	v, _ := value.(int)
  1264  	node.Set("value", v+1)
  1265  	_, err = node.Write()
  1266  	c.Assert(err, jc.ErrorIsNil)
  1267  }