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