launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/uniter/uniter_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter_test 5 6 import ( 7 gc "launchpad.net/gocheck" 8 stdtesting "testing" 9 10 "launchpad.net/juju-core/charm" 11 envtesting "launchpad.net/juju-core/environs/testing" 12 "launchpad.net/juju-core/errors" 13 "launchpad.net/juju-core/instance" 14 "launchpad.net/juju-core/juju/testing" 15 "launchpad.net/juju-core/state" 16 "launchpad.net/juju-core/state/api/params" 17 "launchpad.net/juju-core/state/apiserver/common" 18 commontesting "launchpad.net/juju-core/state/apiserver/common/testing" 19 apiservertesting "launchpad.net/juju-core/state/apiserver/testing" 20 "launchpad.net/juju-core/state/apiserver/uniter" 21 statetesting "launchpad.net/juju-core/state/testing" 22 coretesting "launchpad.net/juju-core/testing" 23 jc "launchpad.net/juju-core/testing/checkers" 24 ) 25 26 func Test(t *stdtesting.T) { 27 coretesting.MgoTestPackage(t) 28 } 29 30 type uniterSuite struct { 31 testing.JujuConnSuite 32 *commontesting.EnvironWatcherTest 33 34 authorizer apiservertesting.FakeAuthorizer 35 resources *common.Resources 36 37 machine0 *state.Machine 38 machine1 *state.Machine 39 wordpress *state.Service 40 wpCharm *state.Charm 41 mysql *state.Service 42 wordpressUnit *state.Unit 43 mysqlUnit *state.Unit 44 45 uniter *uniter.UniterAPI 46 } 47 48 var _ = gc.Suite(&uniterSuite{}) 49 50 func (s *uniterSuite) SetUpTest(c *gc.C) { 51 s.JujuConnSuite.SetUpTest(c) 52 53 s.wpCharm = s.AddTestingCharm(c, "wordpress") 54 // Create two machines, two services and add a unit to each service. 55 var err error 56 s.machine0, err = s.State.AddMachine("quantal", state.JobHostUnits, state.JobManageState, state.JobManageEnviron) 57 c.Assert(err, gc.IsNil) 58 s.machine1, err = s.State.AddMachine("quantal", state.JobHostUnits) 59 c.Assert(err, gc.IsNil) 60 s.wordpress = s.AddTestingService(c, "wordpress", s.wpCharm) 61 s.mysql = s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 62 s.wordpressUnit, err = s.wordpress.AddUnit() 63 c.Assert(err, gc.IsNil) 64 s.mysqlUnit, err = s.mysql.AddUnit() 65 c.Assert(err, gc.IsNil) 66 // Assign each unit to each machine. 67 err = s.wordpressUnit.AssignToMachine(s.machine0) 68 c.Assert(err, gc.IsNil) 69 err = s.mysqlUnit.AssignToMachine(s.machine1) 70 c.Assert(err, gc.IsNil) 71 72 // Create a FakeAuthorizer so we can check permissions, 73 // set up assuming unit 0 has logged in. 74 s.authorizer = apiservertesting.FakeAuthorizer{ 75 Tag: s.wordpressUnit.Tag(), 76 LoggedIn: true, 77 UnitAgent: true, 78 Entity: s.wordpressUnit, 79 } 80 81 // Create the resource registry separately to track invocations to 82 // Register. 83 s.resources = common.NewResources() 84 85 // Create a uniter API for unit 0. 86 s.uniter, err = uniter.NewUniterAPI( 87 s.State, 88 s.resources, 89 s.authorizer, 90 ) 91 c.Assert(err, gc.IsNil) 92 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.uniter, s.State, s.resources, commontesting.NoSecrets) 93 } 94 95 func (s *uniterSuite) TestUniterFailsWithNonUnitAgentUser(c *gc.C) { 96 anAuthorizer := s.authorizer 97 anAuthorizer.UnitAgent = false 98 anUniter, err := uniter.NewUniterAPI(s.State, s.resources, anAuthorizer) 99 c.Assert(err, gc.NotNil) 100 c.Assert(anUniter, gc.IsNil) 101 c.Assert(err, gc.ErrorMatches, "permission denied") 102 } 103 104 func (s *uniterSuite) TestSetStatus(c *gc.C) { 105 err := s.wordpressUnit.SetStatus(params.StatusStarted, "blah", nil) 106 c.Assert(err, gc.IsNil) 107 err = s.mysqlUnit.SetStatus(params.StatusStopped, "foo", nil) 108 c.Assert(err, gc.IsNil) 109 110 args := params.SetStatus{ 111 Entities: []params.SetEntityStatus{ 112 {Tag: "unit-mysql-0", Status: params.StatusError, Info: "not really"}, 113 {Tag: "unit-wordpress-0", Status: params.StatusStopped, Info: "foobar"}, 114 {Tag: "unit-foo-42", Status: params.StatusStarted, Info: "blah"}, 115 }} 116 result, err := s.uniter.SetStatus(args) 117 c.Assert(err, gc.IsNil) 118 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 119 Results: []params.ErrorResult{ 120 {apiservertesting.ErrUnauthorized}, 121 {nil}, 122 {apiservertesting.ErrUnauthorized}, 123 }, 124 }) 125 126 // Verify mysqlUnit - no change. 127 status, info, _, err := s.mysqlUnit.Status() 128 c.Assert(err, gc.IsNil) 129 c.Assert(status, gc.Equals, params.StatusStopped) 130 c.Assert(info, gc.Equals, "foo") 131 // ...wordpressUnit is fine though. 132 status, info, _, err = s.wordpressUnit.Status() 133 c.Assert(err, gc.IsNil) 134 c.Assert(status, gc.Equals, params.StatusStopped) 135 c.Assert(info, gc.Equals, "foobar") 136 } 137 138 func (s *uniterSuite) TestLife(c *gc.C) { 139 // Add a relation wordpress-mysql. 140 rel := s.addRelation(c, "wordpress", "mysql") 141 relUnit, err := rel.Unit(s.wordpressUnit) 142 c.Assert(err, gc.IsNil) 143 err = relUnit.EnterScope(nil) 144 c.Assert(err, gc.IsNil) 145 c.Assert(rel.Life(), gc.Equals, state.Alive) 146 147 // Make the wordpressUnit dead. 148 err = s.wordpressUnit.EnsureDead() 149 c.Assert(err, gc.IsNil) 150 err = s.wordpressUnit.Refresh() 151 c.Assert(err, gc.IsNil) 152 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 153 154 // Add another unit, so the service will stay dying when we 155 // destroy it later. 156 extraUnit, err := s.wordpress.AddUnit() 157 c.Assert(err, gc.IsNil) 158 c.Assert(extraUnit, gc.NotNil) 159 160 // Make the wordpress service dying. 161 err = s.wordpress.Destroy() 162 c.Assert(err, gc.IsNil) 163 err = s.wordpress.Refresh() 164 c.Assert(err, gc.IsNil) 165 c.Assert(s.wordpress.Life(), gc.Equals, state.Dying) 166 167 args := params.Entities{Entities: []params.Entity{ 168 {Tag: "unit-mysql-0"}, 169 {Tag: "unit-wordpress-0"}, 170 {Tag: "unit-foo-42"}, 171 {Tag: "service-mysql"}, 172 {Tag: "service-wordpress"}, 173 {Tag: "service-foo"}, 174 {Tag: "just-foo"}, 175 {Tag: rel.Tag()}, 176 {Tag: "relation-svc1.rel1#svc2.rel2"}, 177 {Tag: "relation-blah"}, 178 }} 179 result, err := s.uniter.Life(args) 180 c.Assert(err, gc.IsNil) 181 c.Assert(result, gc.DeepEquals, params.LifeResults{ 182 Results: []params.LifeResult{ 183 {Error: apiservertesting.ErrUnauthorized}, 184 {Life: "dead"}, 185 {Error: apiservertesting.ErrUnauthorized}, 186 {Error: apiservertesting.ErrUnauthorized}, 187 {Life: "dying"}, 188 {Error: apiservertesting.ErrUnauthorized}, 189 {Error: apiservertesting.ErrUnauthorized}, 190 {Error: apiservertesting.ErrUnauthorized}, 191 {Error: apiservertesting.ErrUnauthorized}, 192 {Error: apiservertesting.ErrUnauthorized}, 193 }, 194 }) 195 } 196 197 func (s *uniterSuite) TestEnsureDead(c *gc.C) { 198 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 199 c.Assert(s.mysqlUnit.Life(), gc.Equals, state.Alive) 200 201 args := params.Entities{Entities: []params.Entity{ 202 {Tag: "unit-mysql-0"}, 203 {Tag: "unit-wordpress-0"}, 204 {Tag: "unit-foo-42"}, 205 }} 206 result, err := s.uniter.EnsureDead(args) 207 c.Assert(err, gc.IsNil) 208 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 209 Results: []params.ErrorResult{ 210 {apiservertesting.ErrUnauthorized}, 211 {nil}, 212 {apiservertesting.ErrUnauthorized}, 213 }, 214 }) 215 216 err = s.wordpressUnit.Refresh() 217 c.Assert(err, gc.IsNil) 218 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 219 err = s.mysqlUnit.Refresh() 220 c.Assert(err, gc.IsNil) 221 c.Assert(s.mysqlUnit.Life(), gc.Equals, state.Alive) 222 223 // Try it again on a Dead unit; should work. 224 args = params.Entities{ 225 Entities: []params.Entity{{Tag: "unit-wordpress-0"}}, 226 } 227 result, err = s.uniter.EnsureDead(args) 228 c.Assert(err, gc.IsNil) 229 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 230 Results: []params.ErrorResult{{nil}}, 231 }) 232 233 // Verify Life is unchanged. 234 err = s.wordpressUnit.Refresh() 235 c.Assert(err, gc.IsNil) 236 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 237 } 238 239 func (s *uniterSuite) assertOneStringsWatcher(c *gc.C, result params.StringsWatchResults, err error) { 240 c.Assert(err, gc.IsNil) 241 c.Assert(result.Results, gc.HasLen, 3) 242 c.Assert(result.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 243 c.Assert(result.Results[1].StringsWatcherId, gc.Equals, "1") 244 c.Assert(result.Results[1].Changes, gc.NotNil) 245 c.Assert(result.Results[1].Error, gc.IsNil) 246 c.Assert(result.Results[2].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 247 248 // Verify the resource was registered and stop when done 249 c.Assert(s.resources.Count(), gc.Equals, 1) 250 resource := s.resources.Get("1") 251 defer statetesting.AssertStop(c, resource) 252 253 // Check that the Watch has consumed the initial event ("returned" in 254 // the Watch call) 255 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 256 wc.AssertNoChange() 257 } 258 259 func (s *uniterSuite) TestWatch(c *gc.C) { 260 c.Assert(s.resources.Count(), gc.Equals, 0) 261 262 args := params.Entities{Entities: []params.Entity{ 263 {Tag: "unit-mysql-0"}, 264 {Tag: "unit-wordpress-0"}, 265 {Tag: "unit-foo-42"}, 266 {Tag: "service-mysql"}, 267 {Tag: "service-wordpress"}, 268 {Tag: "service-foo"}, 269 {Tag: "just-foo"}, 270 }} 271 result, err := s.uniter.Watch(args) 272 c.Assert(err, gc.IsNil) 273 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 274 Results: []params.NotifyWatchResult{ 275 {Error: apiservertesting.ErrUnauthorized}, 276 {NotifyWatcherId: "1"}, 277 {Error: apiservertesting.ErrUnauthorized}, 278 {Error: apiservertesting.ErrUnauthorized}, 279 {NotifyWatcherId: "2"}, 280 {Error: apiservertesting.ErrUnauthorized}, 281 {Error: apiservertesting.ErrUnauthorized}, 282 }, 283 }) 284 285 // Verify the resource was registered and stop when done 286 c.Assert(s.resources.Count(), gc.Equals, 2) 287 resource1 := s.resources.Get("1") 288 defer statetesting.AssertStop(c, resource1) 289 resource2 := s.resources.Get("2") 290 defer statetesting.AssertStop(c, resource2) 291 292 // Check that the Watch has consumed the initial event ("returned" in 293 // the Watch call) 294 wc := statetesting.NewNotifyWatcherC(c, s.State, resource1.(state.NotifyWatcher)) 295 wc.AssertNoChange() 296 wc = statetesting.NewNotifyWatcherC(c, s.State, resource2.(state.NotifyWatcher)) 297 wc.AssertNoChange() 298 } 299 300 func (s *uniterSuite) TestPublicAddress(c *gc.C) { 301 // Try first without setting an address. 302 args := params.Entities{Entities: []params.Entity{ 303 {Tag: "unit-mysql-0"}, 304 {Tag: "unit-wordpress-0"}, 305 {Tag: "unit-foo-42"}, 306 }} 307 expectErr := ¶ms.Error{ 308 Code: params.CodeNoAddressSet, 309 Message: `"unit-wordpress-0" has no public address set`, 310 } 311 result, err := s.uniter.PublicAddress(args) 312 c.Assert(err, gc.IsNil) 313 c.Assert(result, gc.DeepEquals, params.StringResults{ 314 Results: []params.StringResult{ 315 {Error: apiservertesting.ErrUnauthorized}, 316 {Error: expectErr}, 317 {Error: apiservertesting.ErrUnauthorized}, 318 }, 319 }) 320 321 // Now set it an try again. 322 err = s.wordpressUnit.SetPublicAddress("1.2.3.4") 323 c.Assert(err, gc.IsNil) 324 address, ok := s.wordpressUnit.PublicAddress() 325 c.Assert(address, gc.Equals, "1.2.3.4") 326 c.Assert(ok, jc.IsTrue) 327 328 result, err = s.uniter.PublicAddress(args) 329 c.Assert(err, gc.IsNil) 330 c.Assert(result, gc.DeepEquals, params.StringResults{ 331 Results: []params.StringResult{ 332 {Error: apiservertesting.ErrUnauthorized}, 333 {Result: "1.2.3.4"}, 334 {Error: apiservertesting.ErrUnauthorized}, 335 }, 336 }) 337 } 338 339 func (s *uniterSuite) TestSetPublicAddress(c *gc.C) { 340 err := s.wordpressUnit.SetPublicAddress("1.2.3.4") 341 c.Assert(err, gc.IsNil) 342 address, ok := s.wordpressUnit.PublicAddress() 343 c.Assert(address, gc.Equals, "1.2.3.4") 344 c.Assert(ok, jc.IsTrue) 345 346 args := params.SetEntityAddresses{Entities: []params.SetEntityAddress{ 347 {Tag: "unit-mysql-0", Address: "4.3.2.1"}, 348 {Tag: "unit-wordpress-0", Address: "4.4.2.2"}, 349 {Tag: "unit-foo-42", Address: "2.2.4.4"}, 350 }} 351 result, err := s.uniter.SetPublicAddress(args) 352 c.Assert(err, gc.IsNil) 353 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 354 Results: []params.ErrorResult{ 355 {apiservertesting.ErrUnauthorized}, 356 {nil}, 357 {apiservertesting.ErrUnauthorized}, 358 }, 359 }) 360 361 // Verify wordpressUnit's address has changed. 362 err = s.wordpressUnit.Refresh() 363 c.Assert(err, gc.IsNil) 364 address, ok = s.wordpressUnit.PublicAddress() 365 c.Assert(address, gc.Equals, "4.4.2.2") 366 c.Assert(ok, jc.IsTrue) 367 } 368 369 func (s *uniterSuite) TestPrivateAddress(c *gc.C) { 370 args := params.Entities{Entities: []params.Entity{ 371 {Tag: "unit-mysql-0"}, 372 {Tag: "unit-wordpress-0"}, 373 {Tag: "unit-foo-42"}, 374 }} 375 expectErr := ¶ms.Error{ 376 Code: params.CodeNoAddressSet, 377 Message: `"unit-wordpress-0" has no private address set`, 378 } 379 result, err := s.uniter.PrivateAddress(args) 380 c.Assert(err, gc.IsNil) 381 c.Assert(result, gc.DeepEquals, params.StringResults{ 382 Results: []params.StringResult{ 383 {Error: apiservertesting.ErrUnauthorized}, 384 {Error: expectErr}, 385 {Error: apiservertesting.ErrUnauthorized}, 386 }, 387 }) 388 389 // Now set it and try again. 390 err = s.wordpressUnit.SetPrivateAddress("1.2.3.4") 391 c.Assert(err, gc.IsNil) 392 address, ok := s.wordpressUnit.PrivateAddress() 393 c.Assert(address, gc.Equals, "1.2.3.4") 394 c.Assert(ok, jc.IsTrue) 395 396 result, err = s.uniter.PrivateAddress(args) 397 c.Assert(err, gc.IsNil) 398 c.Assert(result, gc.DeepEquals, params.StringResults{ 399 Results: []params.StringResult{ 400 {Error: apiservertesting.ErrUnauthorized}, 401 {Result: "1.2.3.4"}, 402 {Error: apiservertesting.ErrUnauthorized}, 403 }, 404 }) 405 } 406 407 func (s *uniterSuite) TestSetPrivateAddress(c *gc.C) { 408 err := s.wordpressUnit.SetPrivateAddress("1.2.3.4") 409 c.Assert(err, gc.IsNil) 410 address, ok := s.wordpressUnit.PrivateAddress() 411 c.Assert(address, gc.Equals, "1.2.3.4") 412 c.Assert(ok, jc.IsTrue) 413 414 args := params.SetEntityAddresses{Entities: []params.SetEntityAddress{ 415 {Tag: "unit-mysql-0", Address: "4.3.2.1"}, 416 {Tag: "unit-wordpress-0", Address: "4.4.2.2"}, 417 {Tag: "unit-foo-42", Address: "2.2.4.4"}, 418 }} 419 result, err := s.uniter.SetPrivateAddress(args) 420 c.Assert(err, gc.IsNil) 421 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 422 Results: []params.ErrorResult{ 423 {apiservertesting.ErrUnauthorized}, 424 {nil}, 425 {apiservertesting.ErrUnauthorized}, 426 }, 427 }) 428 429 // Verify wordpressUnit's address has changed. 430 err = s.wordpressUnit.Refresh() 431 c.Assert(err, gc.IsNil) 432 address, ok = s.wordpressUnit.PrivateAddress() 433 c.Assert(address, gc.Equals, "4.4.2.2") 434 c.Assert(ok, jc.IsTrue) 435 } 436 437 func (s *uniterSuite) TestResolved(c *gc.C) { 438 err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks) 439 c.Assert(err, gc.IsNil) 440 mode := s.wordpressUnit.Resolved() 441 c.Assert(mode, gc.Equals, state.ResolvedRetryHooks) 442 443 args := params.Entities{Entities: []params.Entity{ 444 {Tag: "unit-mysql-0"}, 445 {Tag: "unit-wordpress-0"}, 446 {Tag: "unit-foo-42"}, 447 }} 448 result, err := s.uniter.Resolved(args) 449 c.Assert(err, gc.IsNil) 450 c.Assert(result, gc.DeepEquals, params.ResolvedModeResults{ 451 Results: []params.ResolvedModeResult{ 452 {Error: apiservertesting.ErrUnauthorized}, 453 {Mode: params.ResolvedMode(mode)}, 454 {Error: apiservertesting.ErrUnauthorized}, 455 }, 456 }) 457 } 458 459 func (s *uniterSuite) TestClearResolved(c *gc.C) { 460 err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks) 461 c.Assert(err, gc.IsNil) 462 mode := s.wordpressUnit.Resolved() 463 c.Assert(mode, gc.Equals, state.ResolvedRetryHooks) 464 465 args := params.Entities{Entities: []params.Entity{ 466 {Tag: "unit-mysql-0"}, 467 {Tag: "unit-wordpress-0"}, 468 {Tag: "unit-foo-42"}, 469 }} 470 result, err := s.uniter.ClearResolved(args) 471 c.Assert(err, gc.IsNil) 472 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 473 Results: []params.ErrorResult{ 474 {apiservertesting.ErrUnauthorized}, 475 {nil}, 476 {apiservertesting.ErrUnauthorized}, 477 }, 478 }) 479 480 // Verify wordpressUnit's resolved mode has changed. 481 err = s.wordpressUnit.Refresh() 482 c.Assert(err, gc.IsNil) 483 mode = s.wordpressUnit.Resolved() 484 c.Assert(mode, gc.Equals, state.ResolvedNone) 485 } 486 487 func (s *uniterSuite) TestGetPrincipal(c *gc.C) { 488 // Add a subordinate to wordpressUnit. 489 _, _, subordinate := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 490 491 principal, ok := subordinate.PrincipalName() 492 c.Assert(principal, gc.Equals, s.wordpressUnit.Name()) 493 c.Assert(ok, jc.IsTrue) 494 495 // First try it as wordpressUnit's agent. 496 args := params.Entities{Entities: []params.Entity{ 497 {Tag: "unit-mysql-0"}, 498 {Tag: "unit-wordpress-0"}, 499 {Tag: subordinate.Tag()}, 500 {Tag: "unit-foo-42"}, 501 }} 502 result, err := s.uniter.GetPrincipal(args) 503 c.Assert(err, gc.IsNil) 504 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 505 Results: []params.StringBoolResult{ 506 {Error: apiservertesting.ErrUnauthorized}, 507 {Result: "", Ok: false, Error: nil}, 508 {Error: apiservertesting.ErrUnauthorized}, 509 {Error: apiservertesting.ErrUnauthorized}, 510 }, 511 }) 512 513 // Now try as subordinate's agent. 514 subAuthorizer := s.authorizer 515 subAuthorizer.Tag = subordinate.Tag() 516 subUniter, err := uniter.NewUniterAPI(s.State, s.resources, subAuthorizer) 517 c.Assert(err, gc.IsNil) 518 519 result, err = subUniter.GetPrincipal(args) 520 c.Assert(err, gc.IsNil) 521 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 522 Results: []params.StringBoolResult{ 523 {Error: apiservertesting.ErrUnauthorized}, 524 {Error: apiservertesting.ErrUnauthorized}, 525 {Result: "unit-wordpress-0", Ok: true, Error: nil}, 526 {Error: apiservertesting.ErrUnauthorized}, 527 }, 528 }) 529 } 530 531 func (s *uniterSuite) addRelatedService(c *gc.C, firstSvc, relatedSvc string, unit *state.Unit) (*state.Relation, *state.Service, *state.Unit) { 532 relatedService := s.AddTestingService(c, relatedSvc, s.AddTestingCharm(c, relatedSvc)) 533 rel := s.addRelation(c, firstSvc, relatedSvc) 534 relUnit, err := rel.Unit(unit) 535 c.Assert(err, gc.IsNil) 536 err = relUnit.EnterScope(nil) 537 c.Assert(err, gc.IsNil) 538 relatedUnit, err := relatedService.Unit(relatedSvc + "/0") 539 c.Assert(err, gc.IsNil) 540 return rel, relatedService, relatedUnit 541 } 542 543 func (s *uniterSuite) TestHasSubordinates(c *gc.C) { 544 // Try first without any subordinates for wordpressUnit. 545 args := params.Entities{Entities: []params.Entity{ 546 {Tag: "unit-mysql-0"}, 547 {Tag: "unit-wordpress-0"}, 548 {Tag: "unit-logging-0"}, 549 {Tag: "unit-foo-42"}, 550 }} 551 result, err := s.uniter.HasSubordinates(args) 552 c.Assert(err, gc.IsNil) 553 c.Assert(result, gc.DeepEquals, params.BoolResults{ 554 Results: []params.BoolResult{ 555 {Error: apiservertesting.ErrUnauthorized}, 556 {Result: false}, 557 {Error: apiservertesting.ErrUnauthorized}, 558 {Error: apiservertesting.ErrUnauthorized}, 559 }, 560 }) 561 562 // Add two subordinates to wordpressUnit and try again. 563 s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 564 s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 565 566 result, err = s.uniter.HasSubordinates(args) 567 c.Assert(err, gc.IsNil) 568 c.Assert(result, gc.DeepEquals, params.BoolResults{ 569 Results: []params.BoolResult{ 570 {Error: apiservertesting.ErrUnauthorized}, 571 {Result: true}, 572 {Error: apiservertesting.ErrUnauthorized}, 573 {Error: apiservertesting.ErrUnauthorized}, 574 }, 575 }) 576 } 577 578 func (s *uniterSuite) TestDestroy(c *gc.C) { 579 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 580 581 args := params.Entities{Entities: []params.Entity{ 582 {Tag: "unit-mysql-0"}, 583 {Tag: "unit-wordpress-0"}, 584 {Tag: "unit-foo-42"}, 585 }} 586 result, err := s.uniter.Destroy(args) 587 c.Assert(err, gc.IsNil) 588 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 589 Results: []params.ErrorResult{ 590 {apiservertesting.ErrUnauthorized}, 591 {nil}, 592 {apiservertesting.ErrUnauthorized}, 593 }, 594 }) 595 596 // Verify wordpressUnit is destroyed and removed. 597 err = s.wordpressUnit.Refresh() 598 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 599 } 600 601 func (s *uniterSuite) TestDestroyAllSubordinates(c *gc.C) { 602 // Add two subordinates to wordpressUnit. 603 _, _, loggingSub := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 604 _, _, monitoringSub := s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 605 c.Assert(loggingSub.Life(), gc.Equals, state.Alive) 606 c.Assert(monitoringSub.Life(), gc.Equals, state.Alive) 607 608 err := s.wordpressUnit.Refresh() 609 c.Assert(err, gc.IsNil) 610 subordinates := s.wordpressUnit.SubordinateNames() 611 c.Assert(subordinates, gc.DeepEquals, []string{"logging/0", "monitoring/0"}) 612 613 args := params.Entities{Entities: []params.Entity{ 614 {Tag: "unit-mysql-0"}, 615 {Tag: "unit-wordpress-0"}, 616 {Tag: "unit-foo-42"}, 617 }} 618 result, err := s.uniter.DestroyAllSubordinates(args) 619 c.Assert(err, gc.IsNil) 620 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 621 Results: []params.ErrorResult{ 622 {apiservertesting.ErrUnauthorized}, 623 {nil}, 624 {apiservertesting.ErrUnauthorized}, 625 }, 626 }) 627 628 // Verify wordpressUnit's subordinates were destroyed. 629 err = loggingSub.Refresh() 630 c.Assert(err, gc.IsNil) 631 c.Assert(loggingSub.Life(), gc.Equals, state.Dying) 632 err = monitoringSub.Refresh() 633 c.Assert(err, gc.IsNil) 634 c.Assert(monitoringSub.Life(), gc.Equals, state.Dying) 635 } 636 637 func (s *uniterSuite) TestCharmURL(c *gc.C) { 638 // Set wordpressUnit's charm URL first. 639 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 640 c.Assert(err, gc.IsNil) 641 curl, ok := s.wordpressUnit.CharmURL() 642 c.Assert(curl, gc.DeepEquals, s.wpCharm.URL()) 643 c.Assert(ok, jc.IsTrue) 644 645 // Make sure wordpress service's charm is what we expect. 646 curl, force := s.wordpress.CharmURL() 647 c.Assert(curl, gc.DeepEquals, s.wpCharm.URL()) 648 c.Assert(force, jc.IsFalse) 649 650 args := params.Entities{Entities: []params.Entity{ 651 {Tag: "unit-mysql-0"}, 652 {Tag: "unit-wordpress-0"}, 653 {Tag: "unit-foo-42"}, 654 {Tag: "service-mysql"}, 655 {Tag: "service-wordpress"}, 656 {Tag: "service-foo"}, 657 {Tag: "just-foo"}, 658 }} 659 result, err := s.uniter.CharmURL(args) 660 c.Assert(err, gc.IsNil) 661 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 662 Results: []params.StringBoolResult{ 663 {Error: apiservertesting.ErrUnauthorized}, 664 {Result: s.wpCharm.String(), Ok: ok}, 665 {Error: apiservertesting.ErrUnauthorized}, 666 {Error: apiservertesting.ErrUnauthorized}, 667 {Result: s.wpCharm.String(), Ok: force}, 668 {Error: apiservertesting.ErrUnauthorized}, 669 {Error: apiservertesting.ErrUnauthorized}, 670 }, 671 }) 672 } 673 674 func (s *uniterSuite) TestSetCharmURL(c *gc.C) { 675 charmUrl, ok := s.wordpressUnit.CharmURL() 676 c.Assert(charmUrl, gc.IsNil) 677 c.Assert(ok, jc.IsFalse) 678 679 args := params.EntitiesCharmURL{Entities: []params.EntityCharmURL{ 680 {Tag: "unit-mysql-0", CharmURL: "cs:quantal/service-42"}, 681 {Tag: "unit-wordpress-0", CharmURL: s.wpCharm.String()}, 682 {Tag: "unit-foo-42", CharmURL: "cs:quantal/foo-321"}, 683 }} 684 result, err := s.uniter.SetCharmURL(args) 685 c.Assert(err, gc.IsNil) 686 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 687 Results: []params.ErrorResult{ 688 {apiservertesting.ErrUnauthorized}, 689 {nil}, 690 {apiservertesting.ErrUnauthorized}, 691 }, 692 }) 693 694 // Verify the charm URL was set. 695 err = s.wordpressUnit.Refresh() 696 c.Assert(err, gc.IsNil) 697 charmUrl, ok = s.wordpressUnit.CharmURL() 698 c.Assert(charmUrl, gc.NotNil) 699 c.Assert(charmUrl.String(), gc.Equals, s.wpCharm.String()) 700 c.Assert(ok, jc.IsTrue) 701 } 702 703 func (s *uniterSuite) TestOpenPort(c *gc.C) { 704 openedPorts := s.wordpressUnit.OpenedPorts() 705 c.Assert(openedPorts, gc.HasLen, 0) 706 707 args := params.EntitiesPorts{Entities: []params.EntityPort{ 708 {Tag: "unit-mysql-0", Protocol: "tcp", Port: 1234}, 709 {Tag: "unit-wordpress-0", Protocol: "udp", Port: 4321}, 710 {Tag: "unit-foo-42", Protocol: "tcp", Port: 42}, 711 }} 712 result, err := s.uniter.OpenPort(args) 713 c.Assert(err, gc.IsNil) 714 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 715 Results: []params.ErrorResult{ 716 {apiservertesting.ErrUnauthorized}, 717 {nil}, 718 {apiservertesting.ErrUnauthorized}, 719 }, 720 }) 721 722 // Verify the wordpressUnit's port is opened. 723 err = s.wordpressUnit.Refresh() 724 c.Assert(err, gc.IsNil) 725 openedPorts = s.wordpressUnit.OpenedPorts() 726 c.Assert(openedPorts, gc.DeepEquals, []instance.Port{ 727 {Protocol: "udp", Number: 4321}, 728 }) 729 } 730 731 func (s *uniterSuite) TestClosePort(c *gc.C) { 732 // Open port udp:4321 in advance on wordpressUnit. 733 err := s.wordpressUnit.OpenPort("udp", 4321) 734 c.Assert(err, gc.IsNil) 735 err = s.wordpressUnit.Refresh() 736 c.Assert(err, gc.IsNil) 737 openedPorts := s.wordpressUnit.OpenedPorts() 738 c.Assert(openedPorts, gc.DeepEquals, []instance.Port{ 739 {Protocol: "udp", Number: 4321}, 740 }) 741 742 args := params.EntitiesPorts{Entities: []params.EntityPort{ 743 {Tag: "unit-mysql-0", Protocol: "tcp", Port: 1234}, 744 {Tag: "unit-wordpress-0", Protocol: "udp", Port: 4321}, 745 {Tag: "unit-foo-42", Protocol: "tcp", Port: 42}, 746 }} 747 result, err := s.uniter.ClosePort(args) 748 c.Assert(err, gc.IsNil) 749 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 750 Results: []params.ErrorResult{ 751 {apiservertesting.ErrUnauthorized}, 752 {nil}, 753 {apiservertesting.ErrUnauthorized}, 754 }, 755 }) 756 757 // Verify the wordpressUnit's port is closed. 758 err = s.wordpressUnit.Refresh() 759 c.Assert(err, gc.IsNil) 760 openedPorts = s.wordpressUnit.OpenedPorts() 761 c.Assert(openedPorts, gc.HasLen, 0) 762 } 763 764 func (s *uniterSuite) TestWatchConfigSettings(c *gc.C) { 765 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 766 c.Assert(err, gc.IsNil) 767 768 c.Assert(s.resources.Count(), gc.Equals, 0) 769 770 args := params.Entities{Entities: []params.Entity{ 771 {Tag: "unit-mysql-0"}, 772 {Tag: "unit-wordpress-0"}, 773 {Tag: "unit-foo-42"}, 774 }} 775 result, err := s.uniter.WatchConfigSettings(args) 776 c.Assert(err, gc.IsNil) 777 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 778 Results: []params.NotifyWatchResult{ 779 {Error: apiservertesting.ErrUnauthorized}, 780 {NotifyWatcherId: "1"}, 781 {Error: apiservertesting.ErrUnauthorized}, 782 }, 783 }) 784 785 // Verify the resource was registered and stop when done 786 c.Assert(s.resources.Count(), gc.Equals, 1) 787 resource := s.resources.Get("1") 788 defer statetesting.AssertStop(c, resource) 789 790 // Check that the Watch has consumed the initial event ("returned" in 791 // the Watch call) 792 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 793 wc.AssertNoChange() 794 } 795 796 func (s *uniterSuite) TestConfigSettings(c *gc.C) { 797 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 798 c.Assert(err, gc.IsNil) 799 settings, err := s.wordpressUnit.ConfigSettings() 800 c.Assert(err, gc.IsNil) 801 c.Assert(settings, gc.DeepEquals, charm.Settings{"blog-title": "My Title"}) 802 803 args := params.Entities{Entities: []params.Entity{ 804 {Tag: "unit-mysql-0"}, 805 {Tag: "unit-wordpress-0"}, 806 {Tag: "unit-foo-42"}, 807 }} 808 result, err := s.uniter.ConfigSettings(args) 809 c.Assert(err, gc.IsNil) 810 c.Assert(result, gc.DeepEquals, params.ConfigSettingsResults{ 811 Results: []params.ConfigSettingsResult{ 812 {Error: apiservertesting.ErrUnauthorized}, 813 {Settings: params.ConfigSettings{"blog-title": "My Title"}}, 814 {Error: apiservertesting.ErrUnauthorized}, 815 }, 816 }) 817 } 818 819 func (s *uniterSuite) TestWatchServiceRelations(c *gc.C) { 820 c.Assert(s.resources.Count(), gc.Equals, 0) 821 822 args := params.Entities{Entities: []params.Entity{ 823 {Tag: "service-mysql"}, 824 {Tag: "service-wordpress"}, 825 {Tag: "service-foo"}, 826 }} 827 result, err := s.uniter.WatchServiceRelations(args) 828 s.assertOneStringsWatcher(c, result, err) 829 } 830 831 func (s *uniterSuite) TestCharmArchiveURL(c *gc.C) { 832 dummyCharm := s.AddTestingCharm(c, "dummy") 833 834 args := params.CharmURLs{URLs: []params.CharmURL{ 835 {URL: "something-invalid"}, 836 {URL: s.wpCharm.String()}, 837 {URL: dummyCharm.String()}, 838 }} 839 result, err := s.uniter.CharmArchiveURL(args) 840 c.Assert(err, gc.IsNil) 841 c.Assert(result, gc.DeepEquals, params.CharmArchiveURLResults{ 842 Results: []params.CharmArchiveURLResult{ 843 {Error: apiservertesting.ErrUnauthorized}, 844 { 845 Result: s.wpCharm.BundleURL().String(), 846 DisableSSLHostnameVerification: false, 847 }, 848 { 849 Result: dummyCharm.BundleURL().String(), 850 DisableSSLHostnameVerification: false, 851 }, 852 }, 853 }) 854 855 envtesting.SetSSLHostnameVerification(c, s.State, false) 856 857 result, err = s.uniter.CharmArchiveURL(args) 858 c.Assert(err, gc.IsNil) 859 c.Assert(result, gc.DeepEquals, params.CharmArchiveURLResults{ 860 Results: []params.CharmArchiveURLResult{ 861 {Error: apiservertesting.ErrUnauthorized}, 862 { 863 Result: s.wpCharm.BundleURL().String(), 864 DisableSSLHostnameVerification: true, 865 }, 866 { 867 Result: dummyCharm.BundleURL().String(), 868 DisableSSLHostnameVerification: true, 869 }, 870 }, 871 }) 872 } 873 874 func (s *uniterSuite) TestCharmArchiveSha256(c *gc.C) { 875 dummyCharm := s.AddTestingCharm(c, "dummy") 876 877 args := params.CharmURLs{URLs: []params.CharmURL{ 878 {URL: "something-invalid"}, 879 {URL: s.wpCharm.String()}, 880 {URL: dummyCharm.String()}, 881 }} 882 result, err := s.uniter.CharmArchiveSha256(args) 883 c.Assert(err, gc.IsNil) 884 c.Assert(result, gc.DeepEquals, params.StringResults{ 885 Results: []params.StringResult{ 886 {Error: apiservertesting.ErrUnauthorized}, 887 {Result: s.wpCharm.BundleSha256()}, 888 {Result: dummyCharm.BundleSha256()}, 889 }, 890 }) 891 } 892 893 func (s *uniterSuite) TestCurrentEnvironUUID(c *gc.C) { 894 env, err := s.State.Environment() 895 c.Assert(err, gc.IsNil) 896 897 result, err := s.uniter.CurrentEnvironUUID() 898 c.Assert(err, gc.IsNil) 899 c.Assert(result, gc.DeepEquals, params.StringResult{Result: env.UUID()}) 900 } 901 902 func (s *uniterSuite) TestCurrentEnvironment(c *gc.C) { 903 env, err := s.State.Environment() 904 c.Assert(err, gc.IsNil) 905 906 result, err := s.uniter.CurrentEnvironment() 907 c.Assert(err, gc.IsNil) 908 expected := params.EnvironmentResult{ 909 Name: env.Name(), 910 UUID: env.UUID(), 911 } 912 c.Assert(result, gc.DeepEquals, expected) 913 } 914 915 func (s *uniterSuite) addRelation(c *gc.C, first, second string) *state.Relation { 916 eps, err := s.State.InferEndpoints([]string{first, second}) 917 c.Assert(err, gc.IsNil) 918 rel, err := s.State.AddRelation(eps...) 919 c.Assert(err, gc.IsNil) 920 return rel 921 } 922 923 func (s *uniterSuite) TestRelation(c *gc.C) { 924 rel := s.addRelation(c, "wordpress", "mysql") 925 wpEp, err := rel.Endpoint("wordpress") 926 c.Assert(err, gc.IsNil) 927 928 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 929 {Relation: "relation-42", Unit: "unit-foo-0"}, 930 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 931 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 932 {Relation: rel.Tag(), Unit: "unit-foo-0"}, 933 {Relation: "relation-blah", Unit: "unit-wordpress-0"}, 934 {Relation: "service-foo", Unit: "user-admin"}, 935 {Relation: "foo", Unit: "bar"}, 936 {Relation: "unit-wordpress-0", Unit: rel.Tag()}, 937 }} 938 result, err := s.uniter.Relation(args) 939 c.Assert(err, gc.IsNil) 940 c.Assert(result, gc.DeepEquals, params.RelationResults{ 941 Results: []params.RelationResult{ 942 {Error: apiservertesting.ErrUnauthorized}, 943 { 944 Id: rel.Id(), 945 Key: rel.String(), 946 Life: params.Life(rel.Life().String()), 947 Endpoint: params.Endpoint{ 948 ServiceName: wpEp.ServiceName, 949 Relation: wpEp.Relation, 950 }, 951 }, 952 {Error: apiservertesting.ErrUnauthorized}, 953 {Error: apiservertesting.ErrUnauthorized}, 954 {Error: apiservertesting.ErrUnauthorized}, 955 {Error: apiservertesting.ErrUnauthorized}, 956 {Error: apiservertesting.ErrUnauthorized}, 957 {Error: apiservertesting.ErrUnauthorized}, 958 }, 959 }) 960 } 961 962 func (s *uniterSuite) TestRelationById(c *gc.C) { 963 rel := s.addRelation(c, "wordpress", "mysql") 964 c.Assert(rel.Id(), gc.Equals, 0) 965 wpEp, err := rel.Endpoint("wordpress") 966 c.Assert(err, gc.IsNil) 967 968 // Add another relation to mysql service, so we can see we can't 969 // get it. 970 otherRel, _, _ := s.addRelatedService(c, "mysql", "logging", s.mysqlUnit) 971 972 args := params.RelationIds{ 973 RelationIds: []int{-1, rel.Id(), otherRel.Id(), 42, 234}, 974 } 975 result, err := s.uniter.RelationById(args) 976 c.Assert(err, gc.IsNil) 977 c.Assert(result, gc.DeepEquals, params.RelationResults{ 978 Results: []params.RelationResult{ 979 {Error: apiservertesting.ErrUnauthorized}, 980 { 981 Id: rel.Id(), 982 Key: rel.String(), 983 Life: params.Life(rel.Life().String()), 984 Endpoint: params.Endpoint{ 985 ServiceName: wpEp.ServiceName, 986 Relation: wpEp.Relation, 987 }, 988 }, 989 {Error: apiservertesting.ErrUnauthorized}, 990 {Error: apiservertesting.ErrUnauthorized}, 991 {Error: apiservertesting.ErrUnauthorized}, 992 }, 993 }) 994 } 995 996 func (s *uniterSuite) TestProviderType(c *gc.C) { 997 cfg, err := s.State.EnvironConfig() 998 c.Assert(err, gc.IsNil) 999 1000 result, err := s.uniter.ProviderType() 1001 c.Assert(err, gc.IsNil) 1002 c.Assert(result, gc.DeepEquals, params.StringResult{Result: cfg.Type()}) 1003 } 1004 1005 func (s *uniterSuite) assertInScope(c *gc.C, relUnit *state.RelationUnit, inScope bool) { 1006 ok, err := relUnit.InScope() 1007 c.Assert(err, gc.IsNil) 1008 c.Assert(ok, gc.Equals, inScope) 1009 } 1010 1011 func (s *uniterSuite) TestEnterScope(c *gc.C) { 1012 // Set wordpressUnit's private address first. 1013 err := s.wordpressUnit.SetPrivateAddress("1.2.3.4") 1014 c.Assert(err, gc.IsNil) 1015 1016 rel := s.addRelation(c, "wordpress", "mysql") 1017 relUnit, err := rel.Unit(s.wordpressUnit) 1018 c.Assert(err, gc.IsNil) 1019 s.assertInScope(c, relUnit, false) 1020 1021 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1022 {Relation: "relation-42", Unit: "unit-foo-0"}, 1023 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1024 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1025 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1026 {Relation: "relation-foo", Unit: "unit-wordpress-0"}, 1027 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1028 {Relation: "foo", Unit: "bar"}, 1029 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1030 {Relation: rel.Tag(), Unit: "service-wordpress"}, 1031 {Relation: rel.Tag(), Unit: "service-mysql"}, 1032 {Relation: rel.Tag(), Unit: "user-admin"}, 1033 }} 1034 result, err := s.uniter.EnterScope(args) 1035 c.Assert(err, gc.IsNil) 1036 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1037 Results: []params.ErrorResult{ 1038 {apiservertesting.ErrUnauthorized}, 1039 {nil}, 1040 {nil}, 1041 {apiservertesting.ErrUnauthorized}, 1042 {apiservertesting.ErrUnauthorized}, 1043 {apiservertesting.ErrUnauthorized}, 1044 {apiservertesting.ErrUnauthorized}, 1045 {apiservertesting.ErrUnauthorized}, 1046 {apiservertesting.ErrUnauthorized}, 1047 {apiservertesting.ErrUnauthorized}, 1048 {apiservertesting.ErrUnauthorized}, 1049 }, 1050 }) 1051 1052 // Verify the scope changes and settings. 1053 s.assertInScope(c, relUnit, true) 1054 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1055 c.Assert(err, gc.IsNil) 1056 c.Assert(readSettings, gc.DeepEquals, map[string]interface{}{ 1057 "private-address": "1.2.3.4", 1058 }) 1059 } 1060 1061 func (s *uniterSuite) TestLeaveScope(c *gc.C) { 1062 rel := s.addRelation(c, "wordpress", "mysql") 1063 relUnit, err := rel.Unit(s.wordpressUnit) 1064 c.Assert(err, gc.IsNil) 1065 settings := map[string]interface{}{ 1066 "some": "settings", 1067 } 1068 err = relUnit.EnterScope(settings) 1069 c.Assert(err, gc.IsNil) 1070 s.assertInScope(c, relUnit, true) 1071 1072 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1073 {Relation: "relation-42", Unit: "unit-foo-0"}, 1074 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1075 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1076 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1077 {Relation: "relation-foo", Unit: "unit-wordpress-0"}, 1078 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1079 {Relation: "foo", Unit: "bar"}, 1080 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1081 {Relation: rel.Tag(), Unit: "service-wordpress"}, 1082 {Relation: rel.Tag(), Unit: "service-mysql"}, 1083 {Relation: rel.Tag(), Unit: "user-admin"}, 1084 }} 1085 result, err := s.uniter.LeaveScope(args) 1086 c.Assert(err, gc.IsNil) 1087 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1088 Results: []params.ErrorResult{ 1089 {apiservertesting.ErrUnauthorized}, 1090 {nil}, 1091 {nil}, 1092 {apiservertesting.ErrUnauthorized}, 1093 {apiservertesting.ErrUnauthorized}, 1094 {apiservertesting.ErrUnauthorized}, 1095 {apiservertesting.ErrUnauthorized}, 1096 {apiservertesting.ErrUnauthorized}, 1097 {apiservertesting.ErrUnauthorized}, 1098 {apiservertesting.ErrUnauthorized}, 1099 {apiservertesting.ErrUnauthorized}, 1100 }, 1101 }) 1102 1103 // Verify the scope changes. 1104 s.assertInScope(c, relUnit, false) 1105 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1106 c.Assert(err, gc.IsNil) 1107 c.Assert(readSettings, gc.DeepEquals, settings) 1108 } 1109 1110 func (s *uniterSuite) TestReadSettings(c *gc.C) { 1111 rel := s.addRelation(c, "wordpress", "mysql") 1112 relUnit, err := rel.Unit(s.wordpressUnit) 1113 c.Assert(err, gc.IsNil) 1114 settings := map[string]interface{}{ 1115 "some": "settings", 1116 } 1117 err = relUnit.EnterScope(settings) 1118 c.Assert(err, gc.IsNil) 1119 s.assertInScope(c, relUnit, true) 1120 1121 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1122 {Relation: "relation-42", Unit: "unit-foo-0"}, 1123 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1124 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1125 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1126 {Relation: "relation-foo", Unit: ""}, 1127 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1128 {Relation: "foo", Unit: "bar"}, 1129 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1130 {Relation: rel.Tag(), Unit: "service-wordpress"}, 1131 {Relation: rel.Tag(), Unit: "service-mysql"}, 1132 {Relation: rel.Tag(), Unit: "user-admin"}, 1133 }} 1134 result, err := s.uniter.ReadSettings(args) 1135 c.Assert(err, gc.IsNil) 1136 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{ 1137 Results: []params.RelationSettingsResult{ 1138 {Error: apiservertesting.ErrUnauthorized}, 1139 {Settings: params.RelationSettings{ 1140 "some": "settings", 1141 }}, 1142 {Error: apiservertesting.ErrUnauthorized}, 1143 {Error: apiservertesting.ErrUnauthorized}, 1144 {Error: apiservertesting.ErrUnauthorized}, 1145 {Error: apiservertesting.ErrUnauthorized}, 1146 {Error: apiservertesting.ErrUnauthorized}, 1147 {Error: apiservertesting.ErrUnauthorized}, 1148 {Error: apiservertesting.ErrUnauthorized}, 1149 {Error: apiservertesting.ErrUnauthorized}, 1150 {Error: apiservertesting.ErrUnauthorized}, 1151 }, 1152 }) 1153 } 1154 1155 func (s *uniterSuite) TestReadSettingsWithNonStringValuesFails(c *gc.C) { 1156 rel := s.addRelation(c, "wordpress", "mysql") 1157 relUnit, err := rel.Unit(s.wordpressUnit) 1158 c.Assert(err, gc.IsNil) 1159 settings := map[string]interface{}{ 1160 "other": "things", 1161 "invalid-bool": false, 1162 } 1163 err = relUnit.EnterScope(settings) 1164 c.Assert(err, gc.IsNil) 1165 s.assertInScope(c, relUnit, true) 1166 1167 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1168 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1169 }} 1170 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool` 1171 result, err := s.uniter.ReadSettings(args) 1172 c.Assert(err, gc.IsNil) 1173 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{ 1174 Results: []params.RelationSettingsResult{ 1175 {Error: ¶ms.Error{Message: expectErr}}, 1176 }, 1177 }) 1178 } 1179 1180 func (s *uniterSuite) TestReadRemoteSettings(c *gc.C) { 1181 rel := s.addRelation(c, "wordpress", "mysql") 1182 relUnit, err := rel.Unit(s.wordpressUnit) 1183 c.Assert(err, gc.IsNil) 1184 settings := map[string]interface{}{ 1185 "some": "settings", 1186 } 1187 err = relUnit.EnterScope(settings) 1188 c.Assert(err, gc.IsNil) 1189 s.assertInScope(c, relUnit, true) 1190 1191 // First test most of the invalid args tests and try to read the 1192 // (unset) remote unit settings. 1193 args := params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{ 1194 {Relation: "relation-42", LocalUnit: "unit-foo-0", RemoteUnit: "foo"}, 1195 {Relation: rel.Tag(), LocalUnit: "unit-wordpress-0", RemoteUnit: "unit-wordpress-0"}, 1196 {Relation: rel.Tag(), LocalUnit: "unit-wordpress-0", RemoteUnit: "unit-mysql-0"}, 1197 {Relation: "relation-42", LocalUnit: "unit-wordpress-0", RemoteUnit: ""}, 1198 {Relation: "relation-foo", LocalUnit: "", RemoteUnit: ""}, 1199 {Relation: "service-wordpress", LocalUnit: "unit-foo-0", RemoteUnit: "user-admin"}, 1200 {Relation: "foo", LocalUnit: "bar", RemoteUnit: "baz"}, 1201 {Relation: rel.Tag(), LocalUnit: "unit-mysql-0", RemoteUnit: "unit-wordpress-0"}, 1202 {Relation: rel.Tag(), LocalUnit: "service-wordpress", RemoteUnit: "service-mysql"}, 1203 {Relation: rel.Tag(), LocalUnit: "service-mysql", RemoteUnit: "foo"}, 1204 {Relation: rel.Tag(), LocalUnit: "user-admin", RemoteUnit: "unit-wordpress-0"}, 1205 }} 1206 result, err := s.uniter.ReadRemoteSettings(args) 1207 // We don't set the remote unit settings on purpose to test the error. 1208 expectErr := `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings not found` 1209 c.Assert(err, gc.IsNil) 1210 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{ 1211 Results: []params.RelationSettingsResult{ 1212 {Error: apiservertesting.ErrUnauthorized}, 1213 {Error: apiservertesting.ErrUnauthorized}, 1214 {Error: ¶ms.Error{Message: expectErr}}, 1215 {Error: apiservertesting.ErrUnauthorized}, 1216 {Error: apiservertesting.ErrUnauthorized}, 1217 {Error: apiservertesting.ErrUnauthorized}, 1218 {Error: apiservertesting.ErrUnauthorized}, 1219 {Error: apiservertesting.ErrUnauthorized}, 1220 {Error: apiservertesting.ErrUnauthorized}, 1221 {Error: apiservertesting.ErrUnauthorized}, 1222 {Error: apiservertesting.ErrUnauthorized}, 1223 }, 1224 }) 1225 // Now leave the mysqlUnit and re-enter with new settings. 1226 relUnit, err = rel.Unit(s.mysqlUnit) 1227 c.Assert(err, gc.IsNil) 1228 settings = map[string]interface{}{ 1229 "other": "things", 1230 } 1231 err = relUnit.LeaveScope() 1232 c.Assert(err, gc.IsNil) 1233 s.assertInScope(c, relUnit, false) 1234 err = relUnit.EnterScope(settings) 1235 c.Assert(err, gc.IsNil) 1236 s.assertInScope(c, relUnit, true) 1237 1238 // Test the remote unit settings can be read. 1239 args = params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{{ 1240 Relation: rel.Tag(), 1241 LocalUnit: "unit-wordpress-0", 1242 RemoteUnit: "unit-mysql-0", 1243 }}} 1244 result, err = s.uniter.ReadRemoteSettings(args) 1245 c.Assert(err, gc.IsNil) 1246 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{ 1247 Results: []params.RelationSettingsResult{ 1248 {Settings: params.RelationSettings{ 1249 "other": "things", 1250 }}, 1251 }, 1252 }) 1253 } 1254 1255 func (s *uniterSuite) TestReadRemoteSettingsWithNonStringValuesFails(c *gc.C) { 1256 rel := s.addRelation(c, "wordpress", "mysql") 1257 relUnit, err := rel.Unit(s.mysqlUnit) 1258 c.Assert(err, gc.IsNil) 1259 settings := map[string]interface{}{ 1260 "other": "things", 1261 "invalid-bool": false, 1262 } 1263 err = relUnit.EnterScope(settings) 1264 c.Assert(err, gc.IsNil) 1265 s.assertInScope(c, relUnit, true) 1266 1267 args := params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{{ 1268 Relation: rel.Tag(), 1269 LocalUnit: "unit-wordpress-0", 1270 RemoteUnit: "unit-mysql-0", 1271 }}} 1272 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool` 1273 result, err := s.uniter.ReadRemoteSettings(args) 1274 c.Assert(err, gc.IsNil) 1275 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{ 1276 Results: []params.RelationSettingsResult{ 1277 {Error: ¶ms.Error{Message: expectErr}}, 1278 }, 1279 }) 1280 } 1281 1282 func (s *uniterSuite) TestUpdateSettings(c *gc.C) { 1283 rel := s.addRelation(c, "wordpress", "mysql") 1284 relUnit, err := rel.Unit(s.wordpressUnit) 1285 c.Assert(err, gc.IsNil) 1286 settings := map[string]interface{}{ 1287 "some": "settings", 1288 "other": "stuff", 1289 } 1290 err = relUnit.EnterScope(settings) 1291 s.assertInScope(c, relUnit, true) 1292 1293 newSettings := params.RelationSettings{ 1294 "some": "different", 1295 "other": "", 1296 } 1297 1298 args := params.RelationUnitsSettings{RelationUnits: []params.RelationUnitSettings{ 1299 {Relation: "relation-42", Unit: "unit-foo-0", Settings: nil}, 1300 {Relation: rel.Tag(), Unit: "unit-wordpress-0", Settings: newSettings}, 1301 {Relation: "relation-42", Unit: "unit-wordpress-0", Settings: nil}, 1302 {Relation: "relation-foo", Unit: "unit-wordpress-0", Settings: nil}, 1303 {Relation: "service-wordpress", Unit: "unit-foo-0", Settings: nil}, 1304 {Relation: "foo", Unit: "bar", Settings: nil}, 1305 {Relation: rel.Tag(), Unit: "unit-mysql-0", Settings: nil}, 1306 {Relation: rel.Tag(), Unit: "service-wordpress", Settings: nil}, 1307 {Relation: rel.Tag(), Unit: "service-mysql", Settings: nil}, 1308 {Relation: rel.Tag(), Unit: "user-admin", Settings: nil}, 1309 }} 1310 result, err := s.uniter.UpdateSettings(args) 1311 c.Assert(err, gc.IsNil) 1312 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1313 Results: []params.ErrorResult{ 1314 {apiservertesting.ErrUnauthorized}, 1315 {nil}, 1316 {apiservertesting.ErrUnauthorized}, 1317 {apiservertesting.ErrUnauthorized}, 1318 {apiservertesting.ErrUnauthorized}, 1319 {apiservertesting.ErrUnauthorized}, 1320 {apiservertesting.ErrUnauthorized}, 1321 {apiservertesting.ErrUnauthorized}, 1322 {apiservertesting.ErrUnauthorized}, 1323 {apiservertesting.ErrUnauthorized}, 1324 }, 1325 }) 1326 1327 // Verify the settings were saved. 1328 s.assertInScope(c, relUnit, true) 1329 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1330 c.Assert(err, gc.IsNil) 1331 c.Assert(readSettings, gc.DeepEquals, map[string]interface{}{ 1332 "some": "different", 1333 }) 1334 } 1335 1336 func (s *uniterSuite) TestWatchRelationUnits(c *gc.C) { 1337 // Add a relation between wordpress and mysql and enter scope with 1338 // mysqlUnit. 1339 rel := s.addRelation(c, "wordpress", "mysql") 1340 myRelUnit, err := rel.Unit(s.mysqlUnit) 1341 c.Assert(err, gc.IsNil) 1342 err = myRelUnit.EnterScope(nil) 1343 c.Assert(err, gc.IsNil) 1344 s.assertInScope(c, myRelUnit, true) 1345 1346 c.Assert(s.resources.Count(), gc.Equals, 0) 1347 1348 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1349 {Relation: "relation-42", Unit: "unit-foo-0"}, 1350 {Relation: rel.Tag(), Unit: "unit-wordpress-0"}, 1351 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1352 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1353 {Relation: "relation-foo", Unit: ""}, 1354 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1355 {Relation: "foo", Unit: "bar"}, 1356 {Relation: rel.Tag(), Unit: "unit-mysql-0"}, 1357 {Relation: rel.Tag(), Unit: "service-wordpress"}, 1358 {Relation: rel.Tag(), Unit: "service-mysql"}, 1359 {Relation: rel.Tag(), Unit: "user-admin"}, 1360 }} 1361 result, err := s.uniter.WatchRelationUnits(args) 1362 c.Assert(err, gc.IsNil) 1363 // UnitSettings versions are volatile, so we don't check them. 1364 // We just make sure the keys of the Changed field are as 1365 // expected. 1366 c.Assert(result.Results, gc.HasLen, len(args.RelationUnits)) 1367 mysqlChanges := result.Results[1].Changes 1368 c.Assert(mysqlChanges, gc.NotNil) 1369 changed, ok := mysqlChanges.Changed["mysql/0"] 1370 c.Assert(ok, jc.IsTrue) 1371 expectChanges := params.RelationUnitsChange{ 1372 Changed: map[string]params.UnitSettings{"mysql/0": changed}, 1373 } 1374 c.Assert(result, gc.DeepEquals, params.RelationUnitsWatchResults{ 1375 Results: []params.RelationUnitsWatchResult{ 1376 {Error: apiservertesting.ErrUnauthorized}, 1377 { 1378 RelationUnitsWatcherId: "1", 1379 Changes: expectChanges, 1380 }, 1381 {Error: apiservertesting.ErrUnauthorized}, 1382 {Error: apiservertesting.ErrUnauthorized}, 1383 {Error: apiservertesting.ErrUnauthorized}, 1384 {Error: apiservertesting.ErrUnauthorized}, 1385 {Error: apiservertesting.ErrUnauthorized}, 1386 {Error: apiservertesting.ErrUnauthorized}, 1387 {Error: apiservertesting.ErrUnauthorized}, 1388 {Error: apiservertesting.ErrUnauthorized}, 1389 {Error: apiservertesting.ErrUnauthorized}, 1390 }, 1391 }) 1392 1393 // Verify the resource was registered and stop when done 1394 c.Assert(s.resources.Count(), gc.Equals, 1) 1395 resource := s.resources.Get("1") 1396 defer statetesting.AssertStop(c, resource) 1397 1398 // Check that the Watch has consumed the initial event ("returned" in 1399 // the Watch call) 1400 wc := statetesting.NewRelationUnitsWatcherC(c, s.State, resource.(state.RelationUnitsWatcher)) 1401 wc.AssertNoChange() 1402 1403 // Leave scope with mysqlUnit and check it's detected. 1404 err = myRelUnit.LeaveScope() 1405 c.Assert(err, gc.IsNil) 1406 s.assertInScope(c, myRelUnit, false) 1407 1408 wc.AssertChange(nil, []string{"mysql/0"}) 1409 } 1410 1411 func (s *uniterSuite) TestAPIAddresses(c *gc.C) { 1412 err := s.machine0.SetAddresses([]instance.Address{ 1413 instance.NewAddress("0.1.2.3"), 1414 }) 1415 c.Assert(err, gc.IsNil) 1416 apiAddresses, err := s.State.APIAddresses() 1417 c.Assert(err, gc.IsNil) 1418 1419 result, err := s.uniter.APIAddresses() 1420 c.Assert(err, gc.IsNil) 1421 c.Assert(result, gc.DeepEquals, params.StringsResult{ 1422 Result: apiAddresses, 1423 }) 1424 } 1425 1426 func (s *uniterSuite) TestGetOwnerTag(c *gc.C) { 1427 tag := s.mysql.Tag() 1428 args := params.Entities{Entities: []params.Entity{ 1429 {Tag: tag}, 1430 }} 1431 result, err := s.uniter.GetOwnerTag(args) 1432 c.Assert(err, gc.IsNil) 1433 c.Assert(result, gc.DeepEquals, params.StringResult{ 1434 Result: "user-admin", 1435 }) 1436 }