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