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 }