func (s *relationUnitSuite) TestWatchRelationUnits(c *gc.C) { // Enter scope with mysqlUnit. myRelUnit, err := s.stateRelation.Unit(s.mysqlUnit) c.Assert(err, gc.IsNil) err = myRelUnit.EnterScope(nil) c.Assert(err, gc.IsNil) s.assertInScope(c, myRelUnit, true) apiRel, err := s.uniter.Relation(s.stateRelation.Tag().String()) c.Assert(err, gc.IsNil) apiUnit, err := s.uniter.Unit(names.NewUnitTag("wordpress/0")) c.Assert(err, gc.IsNil) apiRelUnit, err := apiRel.Unit(apiUnit) c.Assert(err, gc.IsNil) w, err := apiRelUnit.Watch() defer statetesting.AssertStop(c, w) wc := statetesting.NewRelationUnitsWatcherC(c, s.BackingState, w) // Initial event. wc.AssertChange([]string{"mysql/0"}, nil) // Leave scope with mysqlUnit, check it's detected. err = myRelUnit.LeaveScope() c.Assert(err, gc.IsNil) s.assertInScope(c, myRelUnit, false) wc.AssertChange(nil, []string{"mysql/0"}) // Non-change is not reported. err = myRelUnit.LeaveScope() c.Assert(err, gc.IsNil) wc.AssertNoChange() // NOTE: This test is not as exhaustive as the one in state, // because the watcher is already tested there. Here we just // ensure we get the events when we expect them and don't get // them when they're not expected. statetesting.AssertStop(c, w) wc.AssertClosed() }
func (s *WatchScopeSuite) TestProviderRequirerGlobal(c *gc.C) { // Create a pair of services and a relation between them. mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) mysqlEP, err := mysql.Endpoint("server") c.Assert(err, jc.ErrorIsNil) wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) wordpressEP, err := wordpress.Endpoint("db") c.Assert(err, jc.ErrorIsNil) rel, err := s.State.AddRelation(mysqlEP, wordpressEP) c.Assert(err, jc.ErrorIsNil) // Add some units to the services and set their private addresses. addUnit := func(srv *state.Service, sub string, ep state.Endpoint) *state.RelationUnit { unit, err := srv.AddUnit() c.Assert(err, jc.ErrorIsNil) ru, err := rel.Unit(unit) c.Assert(err, jc.ErrorIsNil) c.Assert(ru.Endpoint(), gc.Equals, ep) return ru } msru0 := addUnit(mysql, "ms0", mysqlEP) msru1 := addUnit(mysql, "ms1", mysqlEP) wpru0 := addUnit(wordpress, "wp0", wordpressEP) wpru1 := addUnit(wordpress, "wp1", wordpressEP) // ---------- Single role active ---------- // Watch the relation from the perspective of the first provider unit and // check initial event. msw0 := msru0.Watch() defer testing.AssertStop(c, msw0) msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0) msw0c.AssertChange(nil, nil) msw0c.AssertNoChange() // Join the unit to the relation, change its settings, and check that // nothing apparently happens. err = msru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) changeSettings(c, msru0) msw0c.AssertNoChange() // Join the second provider unit, start its watch, and check what it thinks the // state of the relation is. err = msru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) msw1 := msru1.Watch() defer testing.AssertStop(c, msw1) msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1) msw1c.AssertChange(nil, nil) msw1c.AssertNoChange() // Change the unit's settings, and check that neither provider unit // observes any change. changeSettings(c, msru1) msw1c.AssertNoChange() msw0c.AssertNoChange() // ---------- Two roles active ---------- // Start watches from both requirer units' perspectives, and check that // they see the provider units. expectChanged := []string{"mysql/0", "mysql/1"} wpw0 := wpru0.Watch() defer testing.AssertStop(c, wpw0) wpw0c := testing.NewRelationUnitsWatcherC(c, s.State, wpw0) wpw0c.AssertChange(expectChanged, nil) wpw0c.AssertNoChange() wpw1 := wpru1.Watch() defer testing.AssertStop(c, wpw1) wpw1c := testing.NewRelationUnitsWatcherC(c, s.State, wpw1) wpw1c.AssertChange(expectChanged, nil) wpw1c.AssertNoChange() // Join the first requirer unit, and check the provider units see it. err = wpru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) expectChanged = []string{"wordpress/0"} msw0c.AssertChange(expectChanged, nil) msw0c.AssertNoChange() msw1c.AssertChange(expectChanged, nil) msw1c.AssertNoChange() // Join again, check no-op. err = wpru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) msw0c.AssertNoChange() msw1c.AssertNoChange() // Join the second requirer, and check the provider units see the change. err = wpru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) expectChanged = []string{"wordpress/1"} msw0c.AssertChange(expectChanged, nil) msw0c.AssertNoChange() msw1c.AssertChange(expectChanged, nil) msw1c.AssertNoChange() // Verify that neither requirer has observed any change to the relation. wpw0c.AssertNoChange() wpw1c.AssertNoChange() // Change settings for the first requirer, check providers see it... changeSettings(c, wpru0) expectChanged = []string{"wordpress/0"} msw0c.AssertChange(expectChanged, nil) msw0c.AssertNoChange() msw1c.AssertChange(expectChanged, nil) msw1c.AssertNoChange() // ...and requirers don't. wpw0c.AssertNoChange() wpw1c.AssertNoChange() // Depart the second requirer and check the providers see it... err = wpru1.LeaveScope() c.Assert(err, jc.ErrorIsNil) expectDeparted := []string{"wordpress/1"} msw0c.AssertChange(nil, expectDeparted) msw0c.AssertNoChange() msw1c.AssertChange(nil, expectDeparted) msw1c.AssertNoChange() // ...and the requirers don't. wpw0c.AssertNoChange() wpw1c.AssertNoChange() // Cleanup handled by defers as before. }
func (s *WatchScopeSuite) TestPeer(c *gc.C) { // Create a service and get a peer relation. riak := s.AddTestingService(c, "riak", s.AddTestingCharm(c, "riak")) riakEP, err := riak.Endpoint("ring") c.Assert(err, jc.ErrorIsNil) rels, err := riak.Relations() c.Assert(err, jc.ErrorIsNil) c.Assert(rels, gc.HasLen, 1) rel := rels[0] // Add some units to the service and set their private addresses; get // the relevant RelationUnits. // (Private addresses should be set by their unit agents on // startup; this test does not include that, but Join expects // the information to be available, and uses it to populate the // relation settings node.) addUnit := func(i int) *state.RelationUnit { unit, err := riak.AddUnit() c.Assert(err, jc.ErrorIsNil) err = unit.AssignToNewMachine() c.Assert(err, jc.ErrorIsNil) mId, err := unit.AssignedMachineId() c.Assert(err, jc.ErrorIsNil) machine, err := s.State.Machine(mId) c.Assert(err, jc.ErrorIsNil) privateAddr := network.NewScopedAddress( fmt.Sprintf("riak%d.example.com", i), network.ScopeCloudLocal, ) machine.SetProviderAddresses(privateAddr) ru, err := rel.Unit(unit) c.Assert(err, jc.ErrorIsNil) c.Assert(ru.Endpoint(), gc.Equals, riakEP) return ru } ru0 := addUnit(0) ru1 := addUnit(1) ru2 := addUnit(2) // ---------- Single unit ---------- // Start watching the relation from the perspective of the first unit. w0 := ru0.Watch() defer testing.AssertStop(c, w0) w0c := testing.NewRelationUnitsWatcherC(c, s.State, w0) w0c.AssertChange(nil, nil) w0c.AssertNoChange() // Join the first unit to the relation, and change the settings, and // check that nothing apparently happens. err = ru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) changeSettings(c, ru0) w0c.AssertNoChange() // ---------- Two units ---------- // Now join another unit to the relation... err = ru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) // ...and check that the first relation unit sees the change. expectChanged := []string{"riak/1"} w0c.AssertChange(expectChanged, nil) w0c.AssertNoChange() // Join again, check it's a no-op. err = ru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) w0c.AssertNoChange() // Start watching the relation from the perspective of the second unit, // and check that it sees the right state. w1 := ru1.Watch() defer testing.AssertStop(c, w1) w1c := testing.NewRelationUnitsWatcherC(c, s.State, w1) expectChanged = []string{"riak/0"} w1c.AssertChange(expectChanged, nil) w1c.AssertNoChange() // ---------- Three units ---------- // Whoa, it works. Ok, check the third unit's opinion of the state. w2 := ru2.Watch() defer testing.AssertStop(c, w2) w2c := testing.NewRelationUnitsWatcherC(c, s.State, w2) expectChanged = []string{"riak/0", "riak/1"} w2c.AssertChange(expectChanged, nil) w2c.AssertNoChange() // Join the third unit, and check the first and second units see it. err = ru2.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) expectChanged = []string{"riak/2"} w0c.AssertChange(expectChanged, nil) w0c.AssertNoChange() w1c.AssertChange(expectChanged, nil) w1c.AssertNoChange() // Change the second unit's settings, and check that only // the first and third see changes. changeSettings(c, ru1) w1c.AssertNoChange() expectChanged = []string{"riak/1"} w0c.AssertChange(expectChanged, nil) w0c.AssertNoChange() w2c.AssertChange(expectChanged, nil) w2c.AssertNoChange() // ---------- Two units again ---------- // Depart the second unit, and check that the first and third detect it. err = ru1.LeaveScope() c.Assert(err, jc.ErrorIsNil) expectDeparted := []string{"riak/1"} w0c.AssertChange(nil, expectDeparted) w0c.AssertNoChange() w2c.AssertChange(nil, expectDeparted) w2c.AssertNoChange() // Change its settings, and check the others don't observe anything. changeSettings(c, ru1) w0c.AssertNoChange() w2c.AssertNoChange() // Check no spurious events showed up on the second unit's watch, and check // it closes cleanly. w1c.AssertNoChange() testing.AssertStop(c, w1) // OK, we're done here. Cleanup, and error detection during same, // will be handled by the deferred kill/stop calls. Phew. }
func (s *WatchScopeSuite) TestProviderRequirerContainer(c *gc.C) { // Create a pair of services and a relation between them. mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) mysqlEP, err := mysql.Endpoint("juju-info") c.Assert(err, jc.ErrorIsNil) logging := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) loggingEP, err := logging.Endpoint("info") c.Assert(err, jc.ErrorIsNil) rel, err := s.State.AddRelation(mysqlEP, loggingEP) c.Assert(err, jc.ErrorIsNil) // Change mysqlEP to match the endpoint that will actually be used by the relation. mysqlEP.Scope = charm.ScopeContainer // Add some units to the services and set their private addresses. addUnits := func(i int) (*state.RelationUnit, *state.RelationUnit) { msu, err := mysql.AddUnit() c.Assert(err, jc.ErrorIsNil) msru, err := rel.Unit(msu) c.Assert(err, jc.ErrorIsNil) c.Assert(msru.Endpoint(), gc.Equals, mysqlEP) err = msru.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) err = msru.LeaveScope() c.Assert(err, jc.ErrorIsNil) lgu, err := s.State.Unit("logging/" + strconv.Itoa(i)) c.Assert(err, jc.ErrorIsNil) lgru, err := rel.Unit(lgu) c.Assert(err, jc.ErrorIsNil) c.Assert(lgru.Endpoint(), gc.Equals, loggingEP) return msru, lgru } msru0, lgru0 := addUnits(0) msru1, lgru1 := addUnits(1) // ---------- Single role active ---------- // Start watching the relation from the perspective of the first unit, and // check the initial event. msw0 := msru0.Watch() defer testing.AssertStop(c, msw0) msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0) msw0c.AssertChange(nil, nil) msw0c.AssertNoChange() // Join the unit to the relation, change its settings, and check that // nothing apparently happens. err = msru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) changeSettings(c, msru0) msw0c.AssertNoChange() // Watch the relation from the perspective of the second provider, and // check initial event. msw1 := msru1.Watch() defer testing.AssertStop(c, msw1) msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1) msw1c.AssertChange(nil, nil) msw1c.AssertNoChange() // Join the second provider unit to the relation, and check that neither // watching unit observes any change. err = msru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) msw1c.AssertNoChange() msw0c.AssertNoChange() // Change the unit's settings, and check that nothing apparently happens. changeSettings(c, msru1) msw1c.AssertNoChange() msw0c.AssertNoChange() // ---------- Two roles active ---------- // Start a watch from the first requirer unit's perspective, and check it // only sees the first provider (with which it shares a container). lgw0 := lgru0.Watch() defer testing.AssertStop(c, lgw0) lgw0c := testing.NewRelationUnitsWatcherC(c, s.State, lgw0) expectChanged := []string{"mysql/0"} lgw0c.AssertChange(expectChanged, nil) lgw0c.AssertNoChange() // Join the first requirer unit, and check that only the first provider // observes the change. err = lgru0.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) expectChanged = []string{"logging/0"} msw0c.AssertChange(expectChanged, nil) msw0c.AssertNoChange() msw1c.AssertNoChange() lgw0c.AssertNoChange() // Watch from the second requirer's perspective, and check it only sees the // second provider. lgw1 := lgru1.Watch() defer testing.AssertStop(c, lgw1) lgw1c := testing.NewRelationUnitsWatcherC(c, s.State, lgw1) expectChanged = []string{"mysql/1"} lgw1c.AssertChange(expectChanged, nil) lgw1c.AssertNoChange() // Join the second requirer, and check that the first provider observes it... err = lgru1.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) expectChanged = []string{"logging/1"} msw1c.AssertChange(expectChanged, nil) msw1c.AssertNoChange() // ...and that nothing else sees anything. msw0c.AssertNoChange() lgw0c.AssertNoChange() lgw1c.AssertNoChange() // Change the second provider's settings and check that the second // requirer notices... changeSettings(c, msru1) expectChanged = []string{"mysql/1"} lgw1c.AssertChange(expectChanged, nil) lgw1c.AssertNoChange() // ...but that nothing else does. msw0c.AssertNoChange() msw1c.AssertNoChange() msw0c.AssertNoChange() // Finally, depart the first provider, and check that only the first // requirer observes any change. err = msru0.LeaveScope() c.Assert(err, jc.ErrorIsNil) expectDeparted := []string{"mysql/0"} lgw0c.AssertChange(nil, expectDeparted) lgw0c.AssertNoChange() lgw1c.AssertNoChange() msw0c.AssertNoChange() msw1c.AssertNoChange() // Again, I think we're done, and can be comfortable that the appropriate // connections are in place. }
func (s *uniterSuite) TestWatchRelationUnits(c *gc.C) { // Add a relation between wordpress and mysql and enter scope with // mysqlUnit. rel := s.addRelation(c, "wordpress", "mysql") myRelUnit, err := rel.Unit(s.mysqlUnit) c.Assert(err, gc.IsNil) err = myRelUnit.EnterScope(nil) c.Assert(err, gc.IsNil) s.assertInScope(c, myRelUnit, true) c.Assert(s.resources.Count(), gc.Equals, 0) args := params.RelationUnits{RelationUnits: []params.RelationUnit{ {Relation: "relation-42", Unit: "unit-foo-0"}, {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, {Relation: rel.Tag(), Unit: "unit-mysql-0"}, {Relation: "relation-42", Unit: "unit-wordpress-0"}, {Relation: "relation-foo", Unit: ""}, {Relation: "service-wordpress", Unit: "unit-foo-0"}, {Relation: "foo", Unit: "bar"}, {Relation: rel.Tag(), Unit: "unit-mysql-0"}, {Relation: rel.Tag(), Unit: "service-wordpress"}, {Relation: rel.Tag(), Unit: "service-mysql"}, {Relation: rel.Tag(), Unit: "user-admin"}, }} result, err := s.uniter.WatchRelationUnits(args) c.Assert(err, gc.IsNil) // UnitSettings versions are volatile, so we don't check them. // We just make sure the keys of the Changed field are as // expected. c.Assert(result.Results, gc.HasLen, len(args.RelationUnits)) mysqlChanges := result.Results[1].Changes c.Assert(mysqlChanges, gc.NotNil) changed, ok := mysqlChanges.Changed["mysql/0"] c.Assert(ok, jc.IsTrue) expectChanges := params.RelationUnitsChange{ Changed: map[string]params.UnitSettings{"mysql/0": changed}, } c.Assert(result, gc.DeepEquals, params.RelationUnitsWatchResults{ Results: []params.RelationUnitsWatchResult{ {Error: apiservertesting.ErrUnauthorized}, { RelationUnitsWatcherId: "1", Changes: expectChanges, }, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) // Verify the resource was registered and stop when done c.Assert(s.resources.Count(), gc.Equals, 1) resource := s.resources.Get("1") defer statetesting.AssertStop(c, resource) // Check that the Watch has consumed the initial event ("returned" in // the Watch call) wc := statetesting.NewRelationUnitsWatcherC(c, s.State, resource.(state.RelationUnitsWatcher)) wc.AssertNoChange() // Leave scope with mysqlUnit and check it's detected. err = myRelUnit.LeaveScope() c.Assert(err, gc.IsNil) s.assertInScope(c, myRelUnit, false) wc.AssertChange(nil, []string{"mysql/0"}) }