github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/uniter/uniter_base_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter_test 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/juju/charm.v4" 16 17 "github.com/juju/juju/apiserver/common" 18 "github.com/juju/juju/apiserver/params" 19 apiservertesting "github.com/juju/juju/apiserver/testing" 20 "github.com/juju/juju/apiserver/uniter" 21 "github.com/juju/juju/juju/testing" 22 "github.com/juju/juju/network" 23 "github.com/juju/juju/state" 24 "github.com/juju/juju/state/multiwatcher" 25 statetesting "github.com/juju/juju/state/testing" 26 coretesting "github.com/juju/juju/testing" 27 jujuFactory "github.com/juju/juju/testing/factory" 28 ) 29 30 // uniterBaseSuite implements common testing suite for all API 31 // versions. It's not intended to be used directly or registered as a 32 // suite, but embedded. 33 type uniterBaseSuite struct { 34 testing.JujuConnSuite 35 36 authorizer apiservertesting.FakeAuthorizer 37 resources *common.Resources 38 39 machine0 *state.Machine 40 machine1 *state.Machine 41 wordpress *state.Service 42 wpCharm *state.Charm 43 mysql *state.Service 44 wordpressUnit *state.Unit 45 mysqlUnit *state.Unit 46 meteredUnit *state.Unit 47 } 48 49 func (s *uniterBaseSuite) setUpTest(c *gc.C) { 50 s.JujuConnSuite.SetUpTest(c) 51 52 factory := jujuFactory.NewFactory(s.State) 53 // Create two machines, two services and add a unit to each service. 54 s.machine0 = factory.MakeMachine(c, &jujuFactory.MachineParams{ 55 Series: "quantal", 56 Jobs: []state.MachineJob{state.JobHostUnits, state.JobManageEnviron}, 57 }) 58 s.machine1 = factory.MakeMachine(c, &jujuFactory.MachineParams{ 59 Series: "quantal", 60 Jobs: []state.MachineJob{state.JobHostUnits}, 61 }) 62 s.wpCharm = factory.MakeCharm(c, &jujuFactory.CharmParams{ 63 Name: "wordpress", 64 URL: "cs:quantal/wordpress-3", 65 }) 66 s.wordpress = factory.MakeService(c, &jujuFactory.ServiceParams{ 67 Name: "wordpress", 68 Charm: s.wpCharm, 69 Creator: s.AdminUserTag(c), 70 }) 71 mysqlCharm := factory.MakeCharm(c, &jujuFactory.CharmParams{ 72 Name: "mysql", 73 }) 74 s.mysql = factory.MakeService(c, &jujuFactory.ServiceParams{ 75 Name: "mysql", 76 Charm: mysqlCharm, 77 Creator: s.AdminUserTag(c), 78 }) 79 s.wordpressUnit = factory.MakeUnit(c, &jujuFactory.UnitParams{ 80 Service: s.wordpress, 81 Machine: s.machine0, 82 }) 83 s.mysqlUnit = factory.MakeUnit(c, &jujuFactory.UnitParams{ 84 Service: s.mysql, 85 Machine: s.machine1, 86 }) 87 88 meteredCharm := s.Factory.MakeCharm(c, &jujuFactory.CharmParams{ 89 Name: "metered", 90 URL: "cs:quantal/metered", 91 }) 92 meteredService := s.Factory.MakeService(c, &jujuFactory.ServiceParams{ 93 Charm: meteredCharm, 94 }) 95 s.meteredUnit = s.Factory.MakeUnit(c, &jujuFactory.UnitParams{ 96 Service: meteredService, 97 SetCharmURL: true, 98 }) 99 100 // Create a FakeAuthorizer so we can check permissions, 101 // set up assuming unit 0 has logged in. 102 s.authorizer = apiservertesting.FakeAuthorizer{ 103 Tag: s.wordpressUnit.Tag(), 104 } 105 106 // Create the resource registry separately to track invocations to 107 // Register. 108 s.resources = common.NewResources() 109 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 110 } 111 112 func (s *uniterBaseSuite) testUniterFailsWithNonUnitAgentUser( 113 c *gc.C, 114 factory func(_ *state.State, _ *common.Resources, _ common.Authorizer) error, 115 ) { 116 anAuthorizer := s.authorizer 117 anAuthorizer.Tag = names.NewMachineTag("9") 118 err := factory(s.State, s.resources, anAuthorizer) 119 c.Assert(err, gc.NotNil) 120 c.Assert(err, gc.ErrorMatches, "permission denied") 121 } 122 123 func (s *uniterBaseSuite) testSetStatus( 124 c *gc.C, 125 facade interface { 126 SetStatus(args params.SetStatus) (params.ErrorResults, error) 127 }, 128 ) { 129 err := s.wordpressUnit.SetStatus(state.StatusActive, "blah", nil) 130 c.Assert(err, jc.ErrorIsNil) 131 err = s.mysqlUnit.SetStatus(state.StatusStopping, "foo", nil) 132 c.Assert(err, jc.ErrorIsNil) 133 134 args := params.SetStatus{ 135 Entities: []params.EntityStatus{ 136 {Tag: "unit-mysql-0", Status: params.StatusError, Info: "not really"}, 137 {Tag: "unit-wordpress-0", Status: params.StatusStopping, Info: "foobar"}, 138 {Tag: "unit-foo-42", Status: params.StatusActive, Info: "blah"}, 139 }} 140 result, err := facade.SetStatus(args) 141 c.Assert(err, jc.ErrorIsNil) 142 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 143 Results: []params.ErrorResult{ 144 {apiservertesting.ErrUnauthorized}, 145 {nil}, 146 {apiservertesting.ErrUnauthorized}, 147 }, 148 }) 149 150 // Verify mysqlUnit - no change. 151 status, info, _, err := s.mysqlUnit.Status() 152 c.Assert(err, jc.ErrorIsNil) 153 c.Assert(status, gc.Equals, state.StatusStopping) 154 c.Assert(info, gc.Equals, "foo") 155 // ...wordpressUnit is fine though. 156 status, info, _, err = s.wordpressUnit.Status() 157 c.Assert(err, jc.ErrorIsNil) 158 c.Assert(status, gc.Equals, state.StatusStopping) 159 c.Assert(info, gc.Equals, "foobar") 160 } 161 162 func (s *uniterBaseSuite) testLife( 163 c *gc.C, 164 facade interface { 165 Life(args params.Entities) (params.LifeResults, error) 166 }, 167 ) { 168 // Add a relation wordpress-mysql. 169 rel := s.addRelation(c, "wordpress", "mysql") 170 relUnit, err := rel.Unit(s.wordpressUnit) 171 c.Assert(err, jc.ErrorIsNil) 172 err = relUnit.EnterScope(nil) 173 c.Assert(err, jc.ErrorIsNil) 174 c.Assert(rel.Life(), gc.Equals, state.Alive) 175 176 // Make the wordpressUnit dead. 177 err = s.wordpressUnit.EnsureDead() 178 c.Assert(err, jc.ErrorIsNil) 179 err = s.wordpressUnit.Refresh() 180 c.Assert(err, jc.ErrorIsNil) 181 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 182 183 // Add another unit, so the service will stay dying when we 184 // destroy it later. 185 extraUnit, err := s.wordpress.AddUnit() 186 c.Assert(err, jc.ErrorIsNil) 187 c.Assert(extraUnit, gc.NotNil) 188 189 // Make the wordpress service dying. 190 err = s.wordpress.Destroy() 191 c.Assert(err, jc.ErrorIsNil) 192 err = s.wordpress.Refresh() 193 c.Assert(err, jc.ErrorIsNil) 194 c.Assert(s.wordpress.Life(), gc.Equals, state.Dying) 195 196 args := params.Entities{Entities: []params.Entity{ 197 {Tag: "unit-mysql-0"}, 198 {Tag: "unit-wordpress-0"}, 199 {Tag: "unit-foo-42"}, 200 {Tag: "service-mysql"}, 201 {Tag: "service-wordpress"}, 202 {Tag: "machine-0"}, 203 {Tag: "machine-1"}, 204 {Tag: "machine-42"}, 205 {Tag: "service-foo"}, 206 // TODO(dfc) these aren't valid tags any more 207 // but I hope to restore this test when params.Entity takes 208 // tags, not strings, which is coming soon. 209 // {Tag: "just-foo"}, 210 {Tag: rel.Tag().String()}, 211 {Tag: "relation-svc1.rel1#svc2.rel2"}, 212 // {Tag: "relation-blah"}, 213 }} 214 result, err := facade.Life(args) 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(result, gc.DeepEquals, params.LifeResults{ 217 Results: []params.LifeResult{ 218 {Error: apiservertesting.ErrUnauthorized}, 219 {Life: "dead"}, 220 {Error: apiservertesting.ErrUnauthorized}, 221 {Error: apiservertesting.ErrUnauthorized}, 222 {Life: "dying"}, 223 {Error: apiservertesting.ErrUnauthorized}, 224 {Error: apiservertesting.ErrUnauthorized}, 225 {Error: apiservertesting.ErrUnauthorized}, 226 {Error: apiservertesting.ErrUnauthorized}, 227 // TODO(dfc) see above 228 // {Error: apiservertesting.ErrUnauthorized}, 229 {Error: apiservertesting.ErrUnauthorized}, 230 {Error: apiservertesting.ErrUnauthorized}, 231 // {Error: apiservertesting.ErrUnauthorized}, 232 }, 233 }) 234 } 235 236 func (s *uniterBaseSuite) testEnsureDead( 237 c *gc.C, 238 facade interface { 239 EnsureDead(args params.Entities) (params.ErrorResults, error) 240 }, 241 ) { 242 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 243 c.Assert(s.mysqlUnit.Life(), gc.Equals, state.Alive) 244 245 args := params.Entities{Entities: []params.Entity{ 246 {Tag: "unit-mysql-0"}, 247 {Tag: "unit-wordpress-0"}, 248 {Tag: "unit-foo-42"}, 249 }} 250 result, err := facade.EnsureDead(args) 251 c.Assert(err, jc.ErrorIsNil) 252 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 253 Results: []params.ErrorResult{ 254 {apiservertesting.ErrUnauthorized}, 255 {nil}, 256 {apiservertesting.ErrUnauthorized}, 257 }, 258 }) 259 260 err = s.wordpressUnit.Refresh() 261 c.Assert(err, jc.ErrorIsNil) 262 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 263 err = s.mysqlUnit.Refresh() 264 c.Assert(err, jc.ErrorIsNil) 265 c.Assert(s.mysqlUnit.Life(), gc.Equals, state.Alive) 266 267 // Try it again on a Dead unit; should work. 268 args = params.Entities{ 269 Entities: []params.Entity{{Tag: "unit-wordpress-0"}}, 270 } 271 result, err = facade.EnsureDead(args) 272 c.Assert(err, jc.ErrorIsNil) 273 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 274 Results: []params.ErrorResult{{nil}}, 275 }) 276 277 // Verify Life is unchanged. 278 err = s.wordpressUnit.Refresh() 279 c.Assert(err, jc.ErrorIsNil) 280 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 281 } 282 283 func (s *uniterBaseSuite) testWatch( 284 c *gc.C, 285 facade interface { 286 Watch(args params.Entities) (params.NotifyWatchResults, error) 287 }, 288 ) { 289 c.Assert(s.resources.Count(), gc.Equals, 0) 290 291 args := params.Entities{Entities: []params.Entity{ 292 {Tag: "unit-mysql-0"}, 293 {Tag: "unit-wordpress-0"}, 294 {Tag: "unit-foo-42"}, 295 {Tag: "service-mysql"}, 296 {Tag: "service-wordpress"}, 297 {Tag: "service-foo"}, 298 // TODO(dfc) these aren't valid tags any more 299 // but I hope to restore this test when params.Entity takes 300 // tags, not strings, which is coming soon. 301 // {Tag: "just-foo"}, 302 }} 303 result, err := facade.Watch(args) 304 c.Assert(err, jc.ErrorIsNil) 305 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 306 Results: []params.NotifyWatchResult{ 307 {Error: apiservertesting.ErrUnauthorized}, 308 {NotifyWatcherId: "1"}, 309 {Error: apiservertesting.ErrUnauthorized}, 310 {Error: apiservertesting.ErrUnauthorized}, 311 {NotifyWatcherId: "2"}, 312 {Error: apiservertesting.ErrUnauthorized}, 313 // see above 314 // {Error: apiservertesting.ErrUnauthorized}, 315 }, 316 }) 317 318 // Verify the resource was registered and stop when done 319 c.Assert(s.resources.Count(), gc.Equals, 2) 320 resource1 := s.resources.Get("1") 321 defer statetesting.AssertStop(c, resource1) 322 resource2 := s.resources.Get("2") 323 defer statetesting.AssertStop(c, resource2) 324 325 // Check that the Watch has consumed the initial event ("returned" in 326 // the Watch call) 327 wc := statetesting.NewNotifyWatcherC(c, s.State, resource1.(state.NotifyWatcher)) 328 wc.AssertNoChange() 329 wc = statetesting.NewNotifyWatcherC(c, s.State, resource2.(state.NotifyWatcher)) 330 wc.AssertNoChange() 331 } 332 333 func (s *uniterBaseSuite) testPublicAddress( 334 c *gc.C, 335 facade interface { 336 PublicAddress(args params.Entities) (params.StringResults, error) 337 }, 338 ) { 339 // Try first without setting an address. 340 args := params.Entities{Entities: []params.Entity{ 341 {Tag: "unit-mysql-0"}, 342 {Tag: "unit-wordpress-0"}, 343 {Tag: "unit-foo-42"}, 344 }} 345 expectErr := ¶ms.Error{ 346 Code: params.CodeNoAddressSet, 347 Message: `"unit-wordpress-0" has no public address set`, 348 } 349 result, err := facade.PublicAddress(args) 350 c.Assert(err, jc.ErrorIsNil) 351 c.Assert(result, gc.DeepEquals, params.StringResults{ 352 Results: []params.StringResult{ 353 {Error: apiservertesting.ErrUnauthorized}, 354 {Error: expectErr}, 355 {Error: apiservertesting.ErrUnauthorized}, 356 }, 357 }) 358 359 // Now set it an try again. 360 err = s.machine0.SetAddresses(network.NewAddress("1.2.3.4", network.ScopePublic)) 361 c.Assert(err, jc.ErrorIsNil) 362 address, ok := s.wordpressUnit.PublicAddress() 363 c.Assert(address, gc.Equals, "1.2.3.4") 364 c.Assert(ok, jc.IsTrue) 365 366 result, err = facade.PublicAddress(args) 367 c.Assert(err, jc.ErrorIsNil) 368 c.Assert(result, gc.DeepEquals, params.StringResults{ 369 Results: []params.StringResult{ 370 {Error: apiservertesting.ErrUnauthorized}, 371 {Result: "1.2.3.4"}, 372 {Error: apiservertesting.ErrUnauthorized}, 373 }, 374 }) 375 } 376 377 func (s *uniterBaseSuite) testPrivateAddress( 378 c *gc.C, 379 facade interface { 380 PrivateAddress(args params.Entities) (params.StringResults, error) 381 }, 382 ) { 383 args := params.Entities{Entities: []params.Entity{ 384 {Tag: "unit-mysql-0"}, 385 {Tag: "unit-wordpress-0"}, 386 {Tag: "unit-foo-42"}, 387 }} 388 expectErr := ¶ms.Error{ 389 Code: params.CodeNoAddressSet, 390 Message: `"unit-wordpress-0" has no private address set`, 391 } 392 result, err := facade.PrivateAddress(args) 393 c.Assert(err, jc.ErrorIsNil) 394 c.Assert(result, gc.DeepEquals, params.StringResults{ 395 Results: []params.StringResult{ 396 {Error: apiservertesting.ErrUnauthorized}, 397 {Error: expectErr}, 398 {Error: apiservertesting.ErrUnauthorized}, 399 }, 400 }) 401 402 // Now set it and try again. 403 err = s.machine0.SetAddresses(network.NewAddress("1.2.3.4", network.ScopeCloudLocal)) 404 c.Assert(err, jc.ErrorIsNil) 405 address, ok := s.wordpressUnit.PrivateAddress() 406 c.Assert(address, gc.Equals, "1.2.3.4") 407 c.Assert(ok, jc.IsTrue) 408 409 result, err = facade.PrivateAddress(args) 410 c.Assert(err, jc.ErrorIsNil) 411 c.Assert(result, gc.DeepEquals, params.StringResults{ 412 Results: []params.StringResult{ 413 {Error: apiservertesting.ErrUnauthorized}, 414 {Result: "1.2.3.4"}, 415 {Error: apiservertesting.ErrUnauthorized}, 416 }, 417 }) 418 } 419 420 func (s *uniterBaseSuite) testAvailabilityZone( 421 c *gc.C, 422 facade interface { 423 AvailabilityZone(args params.Entities) (params.StringResults, error) 424 }, 425 ) { 426 s.PatchValue(uniter.GetZone, func(st *state.State, tag names.Tag) (string, error) { 427 return "a_zone", nil 428 }) 429 430 args := params.Entities{Entities: []params.Entity{ 431 {Tag: "unit-wordpress-0"}, 432 }} 433 result, err := facade.AvailabilityZone(args) 434 c.Assert(err, jc.ErrorIsNil) 435 436 c.Check(result, gc.DeepEquals, params.StringResults{ 437 Results: []params.StringResult{ 438 {Result: "a_zone"}, 439 }, 440 }) 441 } 442 443 func (s *uniterBaseSuite) testResolved( 444 c *gc.C, 445 facade interface { 446 Resolved(args params.Entities) (params.ResolvedModeResults, error) 447 }, 448 ) { 449 err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks) 450 c.Assert(err, jc.ErrorIsNil) 451 mode := s.wordpressUnit.Resolved() 452 c.Assert(mode, gc.Equals, state.ResolvedRetryHooks) 453 454 args := params.Entities{Entities: []params.Entity{ 455 {Tag: "unit-mysql-0"}, 456 {Tag: "unit-wordpress-0"}, 457 {Tag: "unit-foo-42"}, 458 }} 459 result, err := facade.Resolved(args) 460 c.Assert(err, jc.ErrorIsNil) 461 c.Assert(result, gc.DeepEquals, params.ResolvedModeResults{ 462 Results: []params.ResolvedModeResult{ 463 {Error: apiservertesting.ErrUnauthorized}, 464 {Mode: params.ResolvedMode(mode)}, 465 {Error: apiservertesting.ErrUnauthorized}, 466 }, 467 }) 468 } 469 470 func (s *uniterBaseSuite) testClearResolved( 471 c *gc.C, 472 facade interface { 473 ClearResolved(args params.Entities) (params.ErrorResults, error) 474 }, 475 ) { 476 err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks) 477 c.Assert(err, jc.ErrorIsNil) 478 mode := s.wordpressUnit.Resolved() 479 c.Assert(mode, gc.Equals, state.ResolvedRetryHooks) 480 481 args := params.Entities{Entities: []params.Entity{ 482 {Tag: "unit-mysql-0"}, 483 {Tag: "unit-wordpress-0"}, 484 {Tag: "unit-foo-42"}, 485 }} 486 result, err := facade.ClearResolved(args) 487 c.Assert(err, jc.ErrorIsNil) 488 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 489 Results: []params.ErrorResult{ 490 {apiservertesting.ErrUnauthorized}, 491 {nil}, 492 {apiservertesting.ErrUnauthorized}, 493 }, 494 }) 495 496 // Verify wordpressUnit's resolved mode has changed. 497 err = s.wordpressUnit.Refresh() 498 c.Assert(err, jc.ErrorIsNil) 499 mode = s.wordpressUnit.Resolved() 500 c.Assert(mode, gc.Equals, state.ResolvedNone) 501 } 502 503 type getPrincipal interface { 504 GetPrincipal(args params.Entities) (params.StringBoolResults, error) 505 } 506 507 func (s *uniterBaseSuite) testGetPrincipal( 508 c *gc.C, 509 facade getPrincipal, 510 factory func(_ *state.State, _ *common.Resources, _ common.Authorizer) (getPrincipal, error), 511 ) { 512 // Add a subordinate to wordpressUnit. 513 _, _, subordinate := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 514 515 principal, ok := subordinate.PrincipalName() 516 c.Assert(principal, gc.Equals, s.wordpressUnit.Name()) 517 c.Assert(ok, jc.IsTrue) 518 519 // First try it as wordpressUnit's agent. 520 args := params.Entities{Entities: []params.Entity{ 521 {Tag: "unit-mysql-0"}, 522 {Tag: "unit-wordpress-0"}, 523 {Tag: subordinate.Tag().String()}, 524 {Tag: "unit-foo-42"}, 525 }} 526 result, err := facade.GetPrincipal(args) 527 c.Assert(err, jc.ErrorIsNil) 528 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 529 Results: []params.StringBoolResult{ 530 {Error: apiservertesting.ErrUnauthorized}, 531 {Result: "", Ok: false, Error: nil}, 532 {Error: apiservertesting.ErrUnauthorized}, 533 {Error: apiservertesting.ErrUnauthorized}, 534 }, 535 }) 536 537 // Now try as subordinate's agent. 538 subAuthorizer := s.authorizer 539 subAuthorizer.Tag = subordinate.Tag() 540 subUniter, err := factory(s.State, s.resources, subAuthorizer) 541 c.Assert(err, jc.ErrorIsNil) 542 543 result, err = subUniter.GetPrincipal(args) 544 c.Assert(err, jc.ErrorIsNil) 545 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 546 Results: []params.StringBoolResult{ 547 {Error: apiservertesting.ErrUnauthorized}, 548 {Error: apiservertesting.ErrUnauthorized}, 549 {Result: "unit-wordpress-0", Ok: true, Error: nil}, 550 {Error: apiservertesting.ErrUnauthorized}, 551 }, 552 }) 553 } 554 555 func (s *uniterBaseSuite) testHasSubordinates( 556 c *gc.C, 557 facade interface { 558 HasSubordinates(args params.Entities) (params.BoolResults, error) 559 }, 560 ) { 561 // Try first without any subordinates for wordpressUnit. 562 args := params.Entities{Entities: []params.Entity{ 563 {Tag: "unit-mysql-0"}, 564 {Tag: "unit-wordpress-0"}, 565 {Tag: "unit-logging-0"}, 566 {Tag: "unit-foo-42"}, 567 }} 568 result, err := facade.HasSubordinates(args) 569 c.Assert(err, jc.ErrorIsNil) 570 c.Assert(result, gc.DeepEquals, params.BoolResults{ 571 Results: []params.BoolResult{ 572 {Error: apiservertesting.ErrUnauthorized}, 573 {Result: false}, 574 {Error: apiservertesting.ErrUnauthorized}, 575 {Error: apiservertesting.ErrUnauthorized}, 576 }, 577 }) 578 579 // Add two subordinates to wordpressUnit and try again. 580 s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 581 s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 582 583 result, err = facade.HasSubordinates(args) 584 c.Assert(err, jc.ErrorIsNil) 585 c.Assert(result, gc.DeepEquals, params.BoolResults{ 586 Results: []params.BoolResult{ 587 {Error: apiservertesting.ErrUnauthorized}, 588 {Result: true}, 589 {Error: apiservertesting.ErrUnauthorized}, 590 {Error: apiservertesting.ErrUnauthorized}, 591 }, 592 }) 593 } 594 595 func (s *uniterBaseSuite) testDestroy( 596 c *gc.C, 597 facade interface { 598 Destroy(args params.Entities) (params.ErrorResults, error) 599 }, 600 ) { 601 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 602 603 args := params.Entities{Entities: []params.Entity{ 604 {Tag: "unit-mysql-0"}, 605 {Tag: "unit-wordpress-0"}, 606 {Tag: "unit-foo-42"}, 607 }} 608 result, err := facade.Destroy(args) 609 c.Assert(err, jc.ErrorIsNil) 610 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 611 Results: []params.ErrorResult{ 612 {apiservertesting.ErrUnauthorized}, 613 {nil}, 614 {apiservertesting.ErrUnauthorized}, 615 }, 616 }) 617 618 // Verify wordpressUnit is destroyed and removed. 619 err = s.wordpressUnit.Refresh() 620 c.Assert(err, jc.Satisfies, errors.IsNotFound) 621 } 622 623 func (s *uniterBaseSuite) testDestroyAllSubordinates( 624 c *gc.C, 625 facade interface { 626 DestroyAllSubordinates(args params.Entities) (params.ErrorResults, error) 627 }, 628 ) { 629 // Add two subordinates to wordpressUnit. 630 _, _, loggingSub := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 631 _, _, monitoringSub := s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 632 c.Assert(loggingSub.Life(), gc.Equals, state.Alive) 633 c.Assert(monitoringSub.Life(), gc.Equals, state.Alive) 634 635 err := s.wordpressUnit.Refresh() 636 c.Assert(err, jc.ErrorIsNil) 637 subordinates := s.wordpressUnit.SubordinateNames() 638 c.Assert(subordinates, gc.DeepEquals, []string{"logging/0", "monitoring/0"}) 639 640 args := params.Entities{Entities: []params.Entity{ 641 {Tag: "unit-mysql-0"}, 642 {Tag: "unit-wordpress-0"}, 643 {Tag: "unit-foo-42"}, 644 }} 645 result, err := facade.DestroyAllSubordinates(args) 646 c.Assert(err, jc.ErrorIsNil) 647 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 648 Results: []params.ErrorResult{ 649 {apiservertesting.ErrUnauthorized}, 650 {nil}, 651 {apiservertesting.ErrUnauthorized}, 652 }, 653 }) 654 655 // Verify wordpressUnit's subordinates were destroyed. 656 err = loggingSub.Refresh() 657 c.Assert(err, jc.ErrorIsNil) 658 c.Assert(loggingSub.Life(), gc.Equals, state.Dying) 659 err = monitoringSub.Refresh() 660 c.Assert(err, jc.ErrorIsNil) 661 c.Assert(monitoringSub.Life(), gc.Equals, state.Dying) 662 } 663 664 func (s *uniterBaseSuite) testCharmURL( 665 c *gc.C, 666 facade interface { 667 CharmURL(args params.Entities) (params.StringBoolResults, error) 668 }, 669 ) { 670 // Set wordpressUnit's charm URL first. 671 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 672 c.Assert(err, jc.ErrorIsNil) 673 curl, ok := s.wordpressUnit.CharmURL() 674 c.Assert(curl, gc.DeepEquals, s.wpCharm.URL()) 675 c.Assert(ok, jc.IsTrue) 676 677 // Make sure wordpress service's charm is what we expect. 678 curl, force := s.wordpress.CharmURL() 679 c.Assert(curl, gc.DeepEquals, s.wpCharm.URL()) 680 c.Assert(force, jc.IsFalse) 681 682 args := params.Entities{Entities: []params.Entity{ 683 {Tag: "unit-mysql-0"}, 684 {Tag: "unit-wordpress-0"}, 685 {Tag: "unit-foo-42"}, 686 {Tag: "service-mysql"}, 687 {Tag: "service-wordpress"}, 688 {Tag: "service-foo"}, 689 // TODO(dfc) these aren't valid tags any more 690 // but I hope to restore this test when params.Entity takes 691 // tags, not strings, which is coming soon. 692 // {Tag: "just-foo"}, 693 }} 694 result, err := facade.CharmURL(args) 695 c.Assert(err, jc.ErrorIsNil) 696 c.Assert(result, gc.DeepEquals, params.StringBoolResults{ 697 Results: []params.StringBoolResult{ 698 {Error: apiservertesting.ErrUnauthorized}, 699 {Result: s.wpCharm.String(), Ok: ok}, 700 {Error: apiservertesting.ErrUnauthorized}, 701 {Error: apiservertesting.ErrUnauthorized}, 702 {Result: s.wpCharm.String(), Ok: force}, 703 {Error: apiservertesting.ErrUnauthorized}, 704 // see above 705 // {Error: apiservertesting.ErrUnauthorized}, 706 }, 707 }) 708 } 709 710 func (s *uniterBaseSuite) testSetCharmURL( 711 c *gc.C, 712 facade interface { 713 SetCharmURL(args params.EntitiesCharmURL) (params.ErrorResults, error) 714 }, 715 ) { 716 _, ok := s.wordpressUnit.CharmURL() 717 c.Assert(ok, jc.IsFalse) 718 719 args := params.EntitiesCharmURL{Entities: []params.EntityCharmURL{ 720 {Tag: "unit-mysql-0", CharmURL: "cs:quantal/service-42"}, 721 {Tag: "unit-wordpress-0", CharmURL: s.wpCharm.String()}, 722 {Tag: "unit-foo-42", CharmURL: "cs:quantal/foo-321"}, 723 }} 724 result, err := facade.SetCharmURL(args) 725 c.Assert(err, jc.ErrorIsNil) 726 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 727 Results: []params.ErrorResult{ 728 {apiservertesting.ErrUnauthorized}, 729 {nil}, 730 {apiservertesting.ErrUnauthorized}, 731 }, 732 }) 733 734 // Verify the charm URL was set. 735 err = s.wordpressUnit.Refresh() 736 c.Assert(err, jc.ErrorIsNil) 737 charmUrl, needsUpgrade := s.wordpressUnit.CharmURL() 738 c.Assert(charmUrl, gc.NotNil) 739 c.Assert(charmUrl.String(), gc.Equals, s.wpCharm.String()) 740 c.Assert(needsUpgrade, jc.IsTrue) 741 } 742 743 func (s *uniterBaseSuite) testOpenPorts( 744 c *gc.C, 745 facade interface { 746 OpenPorts(args params.EntitiesPortRanges) (params.ErrorResults, error) 747 }, 748 ) { 749 openedPorts, err := s.wordpressUnit.OpenedPorts() 750 c.Assert(err, jc.ErrorIsNil) 751 c.Assert(openedPorts, gc.HasLen, 0) 752 753 args := params.EntitiesPortRanges{Entities: []params.EntityPortRange{ 754 {Tag: "unit-mysql-0", Protocol: "tcp", FromPort: 1234, ToPort: 1400}, 755 {Tag: "unit-wordpress-0", Protocol: "udp", FromPort: 4321, ToPort: 5000}, 756 {Tag: "unit-foo-42", Protocol: "tcp", FromPort: 42, ToPort: 42}, 757 }} 758 result, err := facade.OpenPorts(args) 759 c.Assert(err, jc.ErrorIsNil) 760 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 761 Results: []params.ErrorResult{ 762 {apiservertesting.ErrUnauthorized}, 763 {nil}, 764 {apiservertesting.ErrUnauthorized}, 765 }, 766 }) 767 768 // Verify the wordpressUnit's port is opened. 769 openedPorts, err = s.wordpressUnit.OpenedPorts() 770 c.Assert(err, jc.ErrorIsNil) 771 c.Assert(openedPorts, gc.DeepEquals, []network.PortRange{ 772 {Protocol: "udp", FromPort: 4321, ToPort: 5000}, 773 }) 774 } 775 776 func (s *uniterBaseSuite) testClosePorts( 777 c *gc.C, 778 facade interface { 779 ClosePorts(args params.EntitiesPortRanges) (params.ErrorResults, error) 780 }, 781 ) { 782 // Open port udp:4321 in advance on wordpressUnit. 783 err := s.wordpressUnit.OpenPorts("udp", 4321, 5000) 784 c.Assert(err, jc.ErrorIsNil) 785 openedPorts, err := s.wordpressUnit.OpenedPorts() 786 c.Assert(err, jc.ErrorIsNil) 787 c.Assert(openedPorts, gc.DeepEquals, []network.PortRange{ 788 {Protocol: "udp", FromPort: 4321, ToPort: 5000}, 789 }) 790 791 args := params.EntitiesPortRanges{Entities: []params.EntityPortRange{ 792 {Tag: "unit-mysql-0", Protocol: "tcp", FromPort: 1234, ToPort: 1400}, 793 {Tag: "unit-wordpress-0", Protocol: "udp", FromPort: 4321, ToPort: 5000}, 794 {Tag: "unit-foo-42", Protocol: "tcp", FromPort: 42, ToPort: 42}, 795 }} 796 result, err := facade.ClosePorts(args) 797 c.Assert(err, jc.ErrorIsNil) 798 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 799 Results: []params.ErrorResult{ 800 {apiservertesting.ErrUnauthorized}, 801 {nil}, 802 {apiservertesting.ErrUnauthorized}, 803 }, 804 }) 805 806 // Verify the wordpressUnit's port is closed. 807 openedPorts, err = s.wordpressUnit.OpenedPorts() 808 c.Assert(err, jc.ErrorIsNil) 809 c.Assert(openedPorts, gc.HasLen, 0) 810 } 811 812 func (s *uniterBaseSuite) testOpenPort( 813 c *gc.C, 814 facade interface { 815 OpenPort(args params.EntitiesPorts) (params.ErrorResults, error) 816 }, 817 ) { 818 openedPorts, err := s.wordpressUnit.OpenedPorts() 819 c.Assert(err, jc.ErrorIsNil) 820 c.Assert(openedPorts, gc.HasLen, 0) 821 822 args := params.EntitiesPorts{Entities: []params.EntityPort{ 823 {Tag: "unit-mysql-0", Protocol: "tcp", Port: 1234}, 824 {Tag: "unit-wordpress-0", Protocol: "udp", Port: 4321}, 825 {Tag: "unit-foo-42", Protocol: "tcp", Port: 42}, 826 }} 827 result, err := facade.OpenPort(args) 828 c.Assert(err, jc.ErrorIsNil) 829 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 830 Results: []params.ErrorResult{ 831 {apiservertesting.ErrUnauthorized}, 832 {nil}, 833 {apiservertesting.ErrUnauthorized}, 834 }, 835 }) 836 837 // Verify the wordpressUnit's port is opened. 838 openedPorts, err = s.wordpressUnit.OpenedPorts() 839 c.Assert(err, jc.ErrorIsNil) 840 c.Assert(openedPorts, gc.DeepEquals, []network.PortRange{ 841 {Protocol: "udp", FromPort: 4321, ToPort: 4321}, 842 }) 843 } 844 845 func (s *uniterBaseSuite) testClosePort( 846 c *gc.C, 847 facade interface { 848 ClosePort(args params.EntitiesPorts) (params.ErrorResults, error) 849 }, 850 ) { 851 // Open port udp:4321 in advance on wordpressUnit. 852 err := s.wordpressUnit.OpenPort("udp", 4321) 853 c.Assert(err, jc.ErrorIsNil) 854 openedPorts, err := s.wordpressUnit.OpenedPorts() 855 c.Assert(err, jc.ErrorIsNil) 856 c.Assert(openedPorts, gc.DeepEquals, []network.PortRange{ 857 {Protocol: "udp", FromPort: 4321, ToPort: 4321}, 858 }) 859 860 args := params.EntitiesPorts{Entities: []params.EntityPort{ 861 {Tag: "unit-mysql-0", Protocol: "tcp", Port: 1234}, 862 {Tag: "unit-wordpress-0", Protocol: "udp", Port: 4321}, 863 {Tag: "unit-foo-42", Protocol: "tcp", Port: 42}, 864 }} 865 result, err := facade.ClosePort(args) 866 c.Assert(err, jc.ErrorIsNil) 867 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 868 Results: []params.ErrorResult{ 869 {apiservertesting.ErrUnauthorized}, 870 {nil}, 871 {apiservertesting.ErrUnauthorized}, 872 }, 873 }) 874 875 // Verify the wordpressUnit's port is closed. 876 openedPorts, err = s.wordpressUnit.OpenedPorts() 877 c.Assert(err, jc.ErrorIsNil) 878 c.Assert(openedPorts, gc.HasLen, 0) 879 } 880 881 func (s *uniterBaseSuite) testWatchConfigSettings( 882 c *gc.C, 883 facade interface { 884 WatchConfigSettings(args params.Entities) (params.NotifyWatchResults, error) 885 }, 886 ) { 887 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 888 c.Assert(err, jc.ErrorIsNil) 889 890 c.Assert(s.resources.Count(), gc.Equals, 0) 891 892 args := params.Entities{Entities: []params.Entity{ 893 {Tag: "unit-mysql-0"}, 894 {Tag: "unit-wordpress-0"}, 895 {Tag: "unit-foo-42"}, 896 }} 897 result, err := facade.WatchConfigSettings(args) 898 c.Assert(err, jc.ErrorIsNil) 899 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 900 Results: []params.NotifyWatchResult{ 901 {Error: apiservertesting.ErrUnauthorized}, 902 {NotifyWatcherId: "1"}, 903 {Error: apiservertesting.ErrUnauthorized}, 904 }, 905 }) 906 907 // Verify the resource was registered and stop when done 908 c.Assert(s.resources.Count(), gc.Equals, 1) 909 resource := s.resources.Get("1") 910 defer statetesting.AssertStop(c, resource) 911 912 // Check that the Watch has consumed the initial event ("returned" in 913 // the Watch call) 914 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 915 wc.AssertNoChange() 916 } 917 918 type watchActions interface { 919 WatchActionNotifications(args params.Entities) (params.StringsWatchResults, error) 920 } 921 922 func (s *uniterBaseSuite) testWatchActionNotifications(c *gc.C, facade watchActions) { 923 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 924 c.Assert(err, jc.ErrorIsNil) 925 926 c.Assert(s.resources.Count(), gc.Equals, 0) 927 928 args := params.Entities{Entities: []params.Entity{ 929 {Tag: "unit-mysql-0"}, 930 {Tag: "unit-wordpress-0"}, 931 {Tag: "unit-foo-42"}, 932 }} 933 result, err := facade.WatchActionNotifications(args) 934 c.Assert(err, jc.ErrorIsNil) 935 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 936 Results: []params.StringsWatchResult{ 937 {Error: apiservertesting.ErrUnauthorized}, 938 {StringsWatcherId: "1"}, 939 {Error: apiservertesting.ErrUnauthorized}, 940 }, 941 }) 942 943 // Verify the resource was registered and stop when done 944 c.Assert(s.resources.Count(), gc.Equals, 1) 945 resource := s.resources.Get("1") 946 defer statetesting.AssertStop(c, resource) 947 948 // Check that the Watch has consumed the initial event ("returned" in 949 // the Watch call) 950 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 951 wc.AssertNoChange() 952 953 addedAction, err := s.wordpressUnit.AddAction("fakeaction", nil) 954 955 wc.AssertChange(addedAction.Id()) 956 wc.AssertNoChange() 957 } 958 959 func (s *uniterBaseSuite) testWatchPreexistingActions(c *gc.C, facade watchActions) { 960 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 961 c.Assert(err, jc.ErrorIsNil) 962 963 c.Assert(s.resources.Count(), gc.Equals, 0) 964 965 action1, err := s.wordpressUnit.AddAction("fakeaction", nil) 966 c.Assert(err, jc.ErrorIsNil) 967 action2, err := s.wordpressUnit.AddAction("fakeaction", nil) 968 c.Assert(err, jc.ErrorIsNil) 969 970 args := params.Entities{Entities: []params.Entity{ 971 {Tag: "unit-wordpress-0"}, 972 }} 973 974 s.State.StartSync() 975 results, err := facade.WatchActionNotifications(args) 976 c.Assert(err, jc.ErrorIsNil) 977 978 checkUnorderedActionIdsEqual(c, []string{action1.Id(), action2.Id()}, results) 979 980 // Verify the resource was registered and stop when done 981 c.Assert(s.resources.Count(), gc.Equals, 1) 982 resource := s.resources.Get("1") 983 defer statetesting.AssertStop(c, resource) 984 985 // Check that the Watch has consumed the initial event ("returned" in 986 // the Watch call) 987 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 988 wc.AssertNoChange() 989 990 addedAction, err := s.wordpressUnit.AddAction("fakeaction", nil) 991 c.Assert(err, jc.ErrorIsNil) 992 wc.AssertChange(addedAction.Id()) 993 wc.AssertNoChange() 994 } 995 996 func (s *uniterBaseSuite) testWatchActionNotificationsMalformedTag(c *gc.C, facade watchActions) { 997 args := params.Entities{Entities: []params.Entity{ 998 {Tag: "ewenit-mysql-0"}, 999 }} 1000 _, err := facade.WatchActionNotifications(args) 1001 c.Assert(err, gc.NotNil) 1002 c.Assert(err.Error(), gc.Equals, `"ewenit-mysql-0" is not a valid tag`) 1003 } 1004 1005 func (s *uniterBaseSuite) testWatchActionNotificationsMalformedUnitName(c *gc.C, facade watchActions) { 1006 args := params.Entities{Entities: []params.Entity{ 1007 {Tag: "unit-mysql-01"}, 1008 }} 1009 _, err := facade.WatchActionNotifications(args) 1010 c.Assert(err, gc.NotNil) 1011 c.Assert(err.Error(), gc.Equals, `"unit-mysql-01" is not a valid unit tag`) 1012 } 1013 1014 func (s *uniterBaseSuite) testWatchActionNotificationsNotUnit(c *gc.C, facade watchActions) { 1015 action, err := s.mysqlUnit.AddAction("fakeaction", nil) 1016 c.Assert(err, jc.ErrorIsNil) 1017 args := params.Entities{Entities: []params.Entity{ 1018 {Tag: action.Tag().String()}, 1019 }} 1020 _, err = facade.WatchActionNotifications(args) 1021 c.Assert(err, gc.NotNil) 1022 c.Assert(err.Error(), gc.Equals, `"action-`+action.Id()+`" is not a valid unit tag`) 1023 } 1024 1025 func (s *uniterBaseSuite) testWatchActionNotificationsPermissionDenied(c *gc.C, facade watchActions) { 1026 args := params.Entities{Entities: []params.Entity{ 1027 {Tag: "unit-nonexistentgarbage-0"}, 1028 }} 1029 results, err := facade.WatchActionNotifications(args) 1030 c.Assert(err, jc.ErrorIsNil) 1031 c.Assert(results, gc.NotNil) 1032 c.Assert(len(results.Results), gc.Equals, 1) 1033 result := results.Results[0] 1034 c.Assert(result.Error, gc.NotNil) 1035 c.Assert(result.Error.Message, gc.Equals, "permission denied") 1036 } 1037 1038 func (s *uniterBaseSuite) testConfigSettings( 1039 c *gc.C, 1040 facade interface { 1041 ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) 1042 }, 1043 ) { 1044 err := s.wordpressUnit.SetCharmURL(s.wpCharm.URL()) 1045 c.Assert(err, jc.ErrorIsNil) 1046 settings, err := s.wordpressUnit.ConfigSettings() 1047 c.Assert(err, jc.ErrorIsNil) 1048 c.Assert(settings, gc.DeepEquals, charm.Settings{"blog-title": "My Title"}) 1049 1050 args := params.Entities{Entities: []params.Entity{ 1051 {Tag: "unit-mysql-0"}, 1052 {Tag: "unit-wordpress-0"}, 1053 {Tag: "unit-foo-42"}, 1054 }} 1055 result, err := facade.ConfigSettings(args) 1056 c.Assert(err, jc.ErrorIsNil) 1057 c.Assert(result, gc.DeepEquals, params.ConfigSettingsResults{ 1058 Results: []params.ConfigSettingsResult{ 1059 {Error: apiservertesting.ErrUnauthorized}, 1060 {Settings: params.ConfigSettings{"blog-title": "My Title"}}, 1061 {Error: apiservertesting.ErrUnauthorized}, 1062 }, 1063 }) 1064 } 1065 1066 func (s *uniterBaseSuite) testWatchServiceRelations( 1067 c *gc.C, 1068 facade interface { 1069 WatchServiceRelations(args params.Entities) (params.StringsWatchResults, error) 1070 }, 1071 ) { 1072 c.Assert(s.resources.Count(), gc.Equals, 0) 1073 1074 args := params.Entities{Entities: []params.Entity{ 1075 {Tag: "service-mysql"}, 1076 {Tag: "service-wordpress"}, 1077 {Tag: "service-foo"}, 1078 }} 1079 result, err := facade.WatchServiceRelations(args) 1080 s.assertOneStringsWatcher(c, result, err) 1081 } 1082 1083 func (s *uniterBaseSuite) testCharmArchiveSha256( 1084 c *gc.C, 1085 facade interface { 1086 CharmArchiveSha256(args params.CharmURLs) (params.StringResults, error) 1087 }, 1088 ) { 1089 dummyCharm := s.AddTestingCharm(c, "dummy") 1090 1091 args := params.CharmURLs{URLs: []params.CharmURL{ 1092 {URL: "something-invalid"}, 1093 {URL: s.wpCharm.String()}, 1094 {URL: dummyCharm.String()}, 1095 }} 1096 result, err := facade.CharmArchiveSha256(args) 1097 c.Assert(err, jc.ErrorIsNil) 1098 c.Assert(result, gc.DeepEquals, params.StringResults{ 1099 Results: []params.StringResult{ 1100 {Error: apiservertesting.ErrUnauthorized}, 1101 {Result: s.wpCharm.BundleSha256()}, 1102 {Result: dummyCharm.BundleSha256()}, 1103 }, 1104 }) 1105 } 1106 1107 func (s *uniterBaseSuite) testCharmArchiveURLs( 1108 c *gc.C, 1109 facade interface { 1110 CharmArchiveURLs(args params.CharmURLs) (params.StringsResults, error) 1111 }, 1112 ) { 1113 dummyCharm := s.AddTestingCharm(c, "dummy") 1114 1115 hostPorts := [][]network.HostPort{{{ 1116 Address: network.NewAddress("1.2.3.4", network.ScopePublic), 1117 Port: 1234, 1118 }, { 1119 Address: network.NewAddress("0.1.2.3", network.ScopeCloudLocal), 1120 Port: 1234, 1121 }}, {{ 1122 Address: network.NewAddress("1.2.3.5", network.ScopePublic), 1123 Port: 1234, 1124 }}} 1125 err := s.State.SetAPIHostPorts(hostPorts) 1126 c.Assert(err, jc.ErrorIsNil) 1127 1128 args := params.CharmURLs{URLs: []params.CharmURL{ 1129 {URL: "something-invalid"}, 1130 {URL: s.wpCharm.String()}, 1131 {URL: dummyCharm.String()}, 1132 }} 1133 result, err := facade.CharmArchiveURLs(args) 1134 c.Assert(err, jc.ErrorIsNil) 1135 1136 wordpressURLs := []string{ 1137 fmt.Sprintf("https://0.1.2.3:1234/environment/%s/charms?file=%%2A&url=cs%%3Aquantal%%2Fwordpress-3", coretesting.EnvironmentTag.Id()), 1138 fmt.Sprintf("https://1.2.3.5:1234/environment/%s/charms?file=%%2A&url=cs%%3Aquantal%%2Fwordpress-3", coretesting.EnvironmentTag.Id()), 1139 } 1140 dummyURLs := []string{ 1141 fmt.Sprintf("https://0.1.2.3:1234/environment/%s/charms?file=%%2A&url=local%%3Aquantal%%2Fdummy-1", coretesting.EnvironmentTag.Id()), 1142 fmt.Sprintf("https://1.2.3.5:1234/environment/%s/charms?file=%%2A&url=local%%3Aquantal%%2Fdummy-1", coretesting.EnvironmentTag.Id()), 1143 } 1144 1145 c.Assert(result, gc.DeepEquals, params.StringsResults{ 1146 Results: []params.StringsResult{ 1147 {Error: apiservertesting.ErrUnauthorized}, 1148 {Result: wordpressURLs}, 1149 {Result: dummyURLs}, 1150 }, 1151 }) 1152 } 1153 1154 func (s *uniterBaseSuite) testCurrentEnvironUUID( 1155 c *gc.C, 1156 facade interface { 1157 CurrentEnvironUUID() (params.StringResult, error) 1158 }, 1159 ) { 1160 env, err := s.State.Environment() 1161 c.Assert(err, jc.ErrorIsNil) 1162 1163 result, err := facade.CurrentEnvironUUID() 1164 c.Assert(err, jc.ErrorIsNil) 1165 c.Assert(result, gc.DeepEquals, params.StringResult{Result: env.UUID()}) 1166 } 1167 1168 func (s *uniterBaseSuite) testCurrentEnvironment( 1169 c *gc.C, 1170 facade interface { 1171 CurrentEnvironment() (params.EnvironmentResult, error) 1172 }, 1173 ) { 1174 env, err := s.State.Environment() 1175 c.Assert(err, jc.ErrorIsNil) 1176 1177 result, err := facade.CurrentEnvironment() 1178 c.Assert(err, jc.ErrorIsNil) 1179 expected := params.EnvironmentResult{ 1180 Name: env.Name(), 1181 UUID: env.UUID(), 1182 } 1183 c.Assert(result, gc.DeepEquals, expected) 1184 } 1185 1186 type actions interface { 1187 Actions(args params.Entities) (params.ActionsQueryResults, error) 1188 } 1189 1190 func (s *uniterBaseSuite) testActions(c *gc.C, facade actions) { 1191 var actionTests = []struct { 1192 description string 1193 action params.ActionResult 1194 }{{ 1195 description: "A simple action.", 1196 action: params.ActionResult{ 1197 Action: ¶ms.Action{ 1198 Name: "fakeaction", 1199 Parameters: map[string]interface{}{ 1200 "outfile": "foo.txt", 1201 }}, 1202 }, 1203 }, { 1204 description: "An action with nested parameters.", 1205 action: params.ActionResult{ 1206 Action: ¶ms.Action{ 1207 Name: "fakeaction", 1208 Parameters: map[string]interface{}{ 1209 "outfile": "foo.bz2", 1210 "compression": map[string]interface{}{ 1211 "kind": "bzip", 1212 "quality": 5, 1213 }, 1214 }}, 1215 }, 1216 }} 1217 1218 for i, actionTest := range actionTests { 1219 c.Logf("test %d: %s", i, actionTest.description) 1220 1221 a, err := s.wordpressUnit.AddAction( 1222 actionTest.action.Action.Name, 1223 actionTest.action.Action.Parameters) 1224 c.Assert(err, jc.ErrorIsNil) 1225 c.Assert(names.IsValidAction(a.Id()), gc.Equals, true) 1226 actionTag := names.NewActionTag(a.Id()) 1227 c.Assert(a.ActionTag(), gc.Equals, actionTag) 1228 1229 args := params.Entities{ 1230 Entities: []params.Entity{{ 1231 Tag: actionTag.String(), 1232 }}, 1233 } 1234 results, err := facade.Actions(args) 1235 c.Assert(err, jc.ErrorIsNil) 1236 c.Assert(results.Results, gc.HasLen, 1) 1237 1238 actionsQueryResult := results.Results[0] 1239 1240 c.Assert(actionsQueryResult.Error, gc.IsNil) 1241 c.Assert(actionsQueryResult.Action, jc.DeepEquals, actionTest.action) 1242 } 1243 } 1244 1245 func (s *uniterBaseSuite) testActionsNotPresent(c *gc.C, facade actions) { 1246 uuid, err := utils.NewUUID() 1247 c.Assert(err, jc.ErrorIsNil) 1248 args := params.Entities{ 1249 Entities: []params.Entity{{ 1250 Tag: names.NewActionTag(uuid.String()).String(), 1251 }}, 1252 } 1253 results, err := facade.Actions(args) 1254 c.Assert(err, jc.ErrorIsNil) 1255 1256 c.Assert(results.Results, gc.HasLen, 1) 1257 actionsQueryResult := results.Results[0] 1258 c.Assert(actionsQueryResult.Error, gc.NotNil) 1259 c.Assert(actionsQueryResult.Error, gc.ErrorMatches, `action "[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}" not found`) 1260 } 1261 1262 func (s *uniterBaseSuite) testActionsWrongUnit( 1263 c *gc.C, 1264 factory func(_ *state.State, _ *common.Resources, _ common.Authorizer) (actions, error), 1265 ) { 1266 // Action doesn't match unit. 1267 mysqlUnitAuthorizer := apiservertesting.FakeAuthorizer{ 1268 Tag: s.mysqlUnit.Tag(), 1269 } 1270 mysqlUnitFacade, err := factory(s.State, s.resources, mysqlUnitAuthorizer) 1271 c.Assert(err, jc.ErrorIsNil) 1272 1273 action, err := s.wordpressUnit.AddAction("fakeaction", nil) 1274 c.Assert(err, jc.ErrorIsNil) 1275 args := params.Entities{ 1276 Entities: []params.Entity{{ 1277 Tag: action.Tag().String(), 1278 }}, 1279 } 1280 actions, err := mysqlUnitFacade.Actions(args) 1281 c.Assert(err, jc.ErrorIsNil) 1282 c.Assert(len(actions.Results), gc.Equals, 1) 1283 c.Assert(actions.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 1284 } 1285 1286 func (s *uniterBaseSuite) testActionsPermissionDenied(c *gc.C, facade actions) { 1287 action, err := s.mysqlUnit.AddAction("fakeaction", nil) 1288 c.Assert(err, jc.ErrorIsNil) 1289 args := params.Entities{ 1290 Entities: []params.Entity{{ 1291 Tag: action.Tag().String(), 1292 }}, 1293 } 1294 actions, err := facade.Actions(args) 1295 c.Assert(err, jc.ErrorIsNil) 1296 c.Assert(len(actions.Results), gc.Equals, 1) 1297 c.Assert(actions.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 1298 } 1299 1300 type finishActions interface { 1301 FinishActions(args params.ActionExecutionResults) (params.ErrorResults, error) 1302 } 1303 1304 func (s *uniterBaseSuite) testFinishActionsSuccess(c *gc.C, facade finishActions) { 1305 testName := "fakeaction" 1306 testOutput := map[string]interface{}{"output": "completed fakeaction successfully"} 1307 1308 results, err := s.wordpressUnit.CompletedActions() 1309 c.Assert(err, jc.ErrorIsNil) 1310 c.Assert(results, gc.DeepEquals, ([]*state.Action)(nil)) 1311 1312 action, err := s.wordpressUnit.AddAction(testName, nil) 1313 c.Assert(err, jc.ErrorIsNil) 1314 1315 actionResults := params.ActionExecutionResults{ 1316 Results: []params.ActionExecutionResult{{ 1317 ActionTag: action.ActionTag().String(), 1318 Status: params.ActionCompleted, 1319 Results: testOutput, 1320 }}, 1321 } 1322 res, err := facade.FinishActions(actionResults) 1323 c.Assert(err, jc.ErrorIsNil) 1324 c.Assert(res, gc.DeepEquals, params.ErrorResults{Results: []params.ErrorResult{{Error: nil}}}) 1325 1326 results, err = s.wordpressUnit.CompletedActions() 1327 c.Assert(err, jc.ErrorIsNil) 1328 c.Assert(len(results), gc.Equals, 1) 1329 c.Assert(results[0].Status(), gc.Equals, state.ActionCompleted) 1330 res2, errstr := results[0].Results() 1331 c.Assert(errstr, gc.Equals, "") 1332 c.Assert(res2, gc.DeepEquals, testOutput) 1333 c.Assert(results[0].Name(), gc.Equals, testName) 1334 } 1335 1336 func (s *uniterBaseSuite) testFinishActionsFailure(c *gc.C, facade finishActions) { 1337 testName := "fakeaction" 1338 testError := "fakeaction was a dismal failure" 1339 1340 results, err := s.wordpressUnit.CompletedActions() 1341 c.Assert(err, jc.ErrorIsNil) 1342 c.Assert(results, gc.DeepEquals, ([]*state.Action)(nil)) 1343 1344 action, err := s.wordpressUnit.AddAction(testName, nil) 1345 c.Assert(err, jc.ErrorIsNil) 1346 1347 actionResults := params.ActionExecutionResults{ 1348 Results: []params.ActionExecutionResult{{ 1349 ActionTag: action.ActionTag().String(), 1350 Status: params.ActionFailed, 1351 Results: nil, 1352 Message: testError, 1353 }}, 1354 } 1355 res, err := facade.FinishActions(actionResults) 1356 c.Assert(err, jc.ErrorIsNil) 1357 c.Assert(res, gc.DeepEquals, params.ErrorResults{Results: []params.ErrorResult{{Error: nil}}}) 1358 1359 results, err = s.wordpressUnit.CompletedActions() 1360 c.Assert(err, jc.ErrorIsNil) 1361 c.Assert(len(results), gc.Equals, 1) 1362 c.Assert(results[0].Status(), gc.Equals, state.ActionFailed) 1363 res2, errstr := results[0].Results() 1364 c.Assert(errstr, gc.Equals, testError) 1365 c.Assert(res2, gc.DeepEquals, map[string]interface{}{}) 1366 c.Assert(results[0].Name(), gc.Equals, testName) 1367 } 1368 1369 func (s *uniterBaseSuite) testFinishActionsAuthAccess(c *gc.C, facade finishActions) { 1370 good, err := s.wordpressUnit.AddAction("fakeaction", nil) 1371 c.Assert(err, jc.ErrorIsNil) 1372 1373 bad, err := s.mysqlUnit.AddAction("fakeaction", nil) 1374 c.Assert(err, jc.ErrorIsNil) 1375 1376 var tests = []struct { 1377 actionTag names.ActionTag 1378 err error 1379 }{ 1380 {actionTag: good.ActionTag(), err: nil}, 1381 {actionTag: bad.ActionTag(), err: common.ErrPerm}, 1382 } 1383 1384 // Queue up actions from tests 1385 actionResults := params.ActionExecutionResults{Results: make([]params.ActionExecutionResult, len(tests))} 1386 for i, test := range tests { 1387 actionResults.Results[i] = params.ActionExecutionResult{ 1388 ActionTag: test.actionTag.String(), 1389 Status: params.ActionCompleted, 1390 Results: map[string]interface{}{}, 1391 } 1392 } 1393 1394 // Invoke FinishActions 1395 res, err := facade.FinishActions(actionResults) 1396 c.Assert(err, jc.ErrorIsNil) 1397 1398 // Verify permissions errors for actions queued on different unit 1399 for i, result := range res.Results { 1400 expected := tests[i].err 1401 if expected != nil { 1402 c.Assert(result.Error, gc.NotNil) 1403 c.Assert(result.Error.Error(), gc.Equals, expected.Error()) 1404 } else { 1405 c.Assert(result.Error, gc.IsNil) 1406 } 1407 } 1408 } 1409 1410 type beginActions interface { 1411 BeginActions(args params.Entities) (params.ErrorResults, error) 1412 } 1413 1414 func (s *uniterBaseSuite) testBeginActions(c *gc.C, facade beginActions) { 1415 ten_seconds_ago := time.Now().Add(-10 * time.Second) 1416 good, err := s.wordpressUnit.AddAction("fakeaction", nil) 1417 c.Assert(err, jc.ErrorIsNil) 1418 1419 running, err := s.wordpressUnit.RunningActions() 1420 c.Assert(err, jc.ErrorIsNil) 1421 c.Assert(len(running), gc.Equals, 0, gc.Commentf("expected no running actions, got %d", len(running))) 1422 1423 args := params.Entities{Entities: []params.Entity{{Tag: good.ActionTag().String()}}} 1424 res, err := facade.BeginActions(args) 1425 c.Assert(err, jc.ErrorIsNil) 1426 c.Assert(len(res.Results), gc.Equals, 1) 1427 c.Assert(res.Results[0].Error, gc.IsNil) 1428 1429 running, err = s.wordpressUnit.RunningActions() 1430 c.Assert(err, jc.ErrorIsNil) 1431 c.Assert(len(running), gc.Equals, 1, gc.Commentf("expected one running action, got %d", len(running))) 1432 c.Assert(running[0].ActionTag(), gc.Equals, good.ActionTag()) 1433 enqueued, started := running[0].Enqueued(), running[0].Started() 1434 c.Assert(ten_seconds_ago.Before(enqueued), jc.IsTrue, gc.Commentf("enqueued time should be after 10 seconds ago")) 1435 c.Assert(ten_seconds_ago.Before(started), jc.IsTrue, gc.Commentf("started time should be after 10 seconds ago")) 1436 c.Assert(started.After(enqueued) || started.Equal(enqueued), jc.IsTrue, gc.Commentf("started should be after or equal to enqueued time")) 1437 } 1438 1439 func (s *uniterBaseSuite) testRelation( 1440 c *gc.C, 1441 facade interface { 1442 Relation(args params.RelationUnits) (params.RelationResults, error) 1443 }, 1444 ) { 1445 rel := s.addRelation(c, "wordpress", "mysql") 1446 wpEp, err := rel.Endpoint("wordpress") 1447 c.Assert(err, jc.ErrorIsNil) 1448 1449 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1450 {Relation: "relation-42", Unit: "unit-foo-0"}, 1451 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1452 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1453 {Relation: rel.Tag().String(), Unit: "unit-foo-0"}, 1454 {Relation: "relation-blah", Unit: "unit-wordpress-0"}, 1455 {Relation: "service-foo", Unit: "user-foo"}, 1456 {Relation: "foo", Unit: "bar"}, 1457 {Relation: "unit-wordpress-0", Unit: rel.Tag().String()}, 1458 }} 1459 result, err := facade.Relation(args) 1460 c.Assert(err, jc.ErrorIsNil) 1461 c.Assert(result, gc.DeepEquals, params.RelationResults{ 1462 Results: []params.RelationResult{ 1463 {Error: apiservertesting.ErrUnauthorized}, 1464 { 1465 Id: rel.Id(), 1466 Key: rel.String(), 1467 Life: params.Life(rel.Life().String()), 1468 Endpoint: multiwatcher.Endpoint{ 1469 ServiceName: wpEp.ServiceName, 1470 Relation: wpEp.Relation, 1471 }, 1472 }, 1473 {Error: apiservertesting.ErrUnauthorized}, 1474 {Error: apiservertesting.ErrUnauthorized}, 1475 {Error: apiservertesting.ErrUnauthorized}, 1476 {Error: apiservertesting.ErrUnauthorized}, 1477 {Error: apiservertesting.ErrUnauthorized}, 1478 {Error: apiservertesting.ErrUnauthorized}, 1479 }, 1480 }) 1481 } 1482 1483 func (s *uniterBaseSuite) testRelationById( 1484 c *gc.C, 1485 facade interface { 1486 RelationById(args params.RelationIds) (params.RelationResults, error) 1487 }, 1488 ) { 1489 rel := s.addRelation(c, "wordpress", "mysql") 1490 c.Assert(rel.Id(), gc.Equals, 0) 1491 wpEp, err := rel.Endpoint("wordpress") 1492 c.Assert(err, jc.ErrorIsNil) 1493 1494 // Add another relation to mysql service, so we can see we can't 1495 // get it. 1496 otherRel, _, _ := s.addRelatedService(c, "mysql", "logging", s.mysqlUnit) 1497 1498 args := params.RelationIds{ 1499 RelationIds: []int{-1, rel.Id(), otherRel.Id(), 42, 234}, 1500 } 1501 result, err := facade.RelationById(args) 1502 c.Assert(err, jc.ErrorIsNil) 1503 c.Assert(result, gc.DeepEquals, params.RelationResults{ 1504 Results: []params.RelationResult{ 1505 {Error: apiservertesting.ErrUnauthorized}, 1506 { 1507 Id: rel.Id(), 1508 Key: rel.String(), 1509 Life: params.Life(rel.Life().String()), 1510 Endpoint: multiwatcher.Endpoint{ 1511 ServiceName: wpEp.ServiceName, 1512 Relation: wpEp.Relation, 1513 }, 1514 }, 1515 {Error: apiservertesting.ErrUnauthorized}, 1516 {Error: apiservertesting.ErrUnauthorized}, 1517 {Error: apiservertesting.ErrUnauthorized}, 1518 }, 1519 }) 1520 } 1521 1522 func (s *uniterBaseSuite) testProviderType( 1523 c *gc.C, 1524 facade interface { 1525 ProviderType() (params.StringResult, error) 1526 }, 1527 ) { 1528 cfg, err := s.State.EnvironConfig() 1529 c.Assert(err, jc.ErrorIsNil) 1530 1531 result, err := facade.ProviderType() 1532 c.Assert(err, jc.ErrorIsNil) 1533 c.Assert(result, gc.DeepEquals, params.StringResult{Result: cfg.Type()}) 1534 } 1535 1536 func (s *uniterBaseSuite) testEnterScope( 1537 c *gc.C, 1538 facade interface { 1539 EnterScope(args params.RelationUnits) (params.ErrorResults, error) 1540 }, 1541 ) { 1542 // Set wordpressUnit's private address first. 1543 err := s.machine0.SetAddresses(network.NewAddress("1.2.3.4", network.ScopeCloudLocal)) 1544 c.Assert(err, jc.ErrorIsNil) 1545 1546 rel := s.addRelation(c, "wordpress", "mysql") 1547 relUnit, err := rel.Unit(s.wordpressUnit) 1548 c.Assert(err, jc.ErrorIsNil) 1549 s.assertInScope(c, relUnit, false) 1550 1551 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1552 {Relation: "relation-42", Unit: "unit-foo-0"}, 1553 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1554 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1555 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1556 {Relation: "relation-foo", Unit: "unit-wordpress-0"}, 1557 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1558 {Relation: "foo", Unit: "bar"}, 1559 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1560 {Relation: rel.Tag().String(), Unit: "service-wordpress"}, 1561 {Relation: rel.Tag().String(), Unit: "service-mysql"}, 1562 {Relation: rel.Tag().String(), Unit: "user-foo"}, 1563 }} 1564 result, err := facade.EnterScope(args) 1565 c.Assert(err, jc.ErrorIsNil) 1566 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1567 Results: []params.ErrorResult{ 1568 {apiservertesting.ErrUnauthorized}, 1569 {nil}, 1570 {nil}, 1571 {apiservertesting.ErrUnauthorized}, 1572 {apiservertesting.ErrUnauthorized}, 1573 {apiservertesting.ErrUnauthorized}, 1574 {apiservertesting.ErrUnauthorized}, 1575 {apiservertesting.ErrUnauthorized}, 1576 {apiservertesting.ErrUnauthorized}, 1577 {apiservertesting.ErrUnauthorized}, 1578 {apiservertesting.ErrUnauthorized}, 1579 }, 1580 }) 1581 1582 // Verify the scope changes and settings. 1583 s.assertInScope(c, relUnit, true) 1584 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1585 c.Assert(err, jc.ErrorIsNil) 1586 c.Assert(readSettings, gc.DeepEquals, map[string]interface{}{ 1587 "private-address": "1.2.3.4", 1588 }) 1589 } 1590 1591 func (s *uniterBaseSuite) testLeaveScope( 1592 c *gc.C, 1593 facade interface { 1594 LeaveScope(args params.RelationUnits) (params.ErrorResults, error) 1595 }, 1596 ) { 1597 rel := s.addRelation(c, "wordpress", "mysql") 1598 relUnit, err := rel.Unit(s.wordpressUnit) 1599 c.Assert(err, jc.ErrorIsNil) 1600 settings := map[string]interface{}{ 1601 "some": "settings", 1602 } 1603 err = relUnit.EnterScope(settings) 1604 c.Assert(err, jc.ErrorIsNil) 1605 s.assertInScope(c, relUnit, true) 1606 1607 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1608 {Relation: "relation-42", Unit: "unit-foo-0"}, 1609 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1610 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1611 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1612 {Relation: "relation-foo", Unit: "unit-wordpress-0"}, 1613 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1614 {Relation: "foo", Unit: "bar"}, 1615 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1616 {Relation: rel.Tag().String(), Unit: "service-wordpress"}, 1617 {Relation: rel.Tag().String(), Unit: "service-mysql"}, 1618 {Relation: rel.Tag().String(), Unit: "user-foo"}, 1619 }} 1620 result, err := facade.LeaveScope(args) 1621 c.Assert(err, jc.ErrorIsNil) 1622 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1623 Results: []params.ErrorResult{ 1624 {apiservertesting.ErrUnauthorized}, 1625 {nil}, 1626 {nil}, 1627 {apiservertesting.ErrUnauthorized}, 1628 {apiservertesting.ErrUnauthorized}, 1629 {apiservertesting.ErrUnauthorized}, 1630 {apiservertesting.ErrUnauthorized}, 1631 {apiservertesting.ErrUnauthorized}, 1632 {apiservertesting.ErrUnauthorized}, 1633 {apiservertesting.ErrUnauthorized}, 1634 {apiservertesting.ErrUnauthorized}, 1635 }, 1636 }) 1637 1638 // Verify the scope changes. 1639 s.assertInScope(c, relUnit, false) 1640 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1641 c.Assert(err, jc.ErrorIsNil) 1642 c.Assert(readSettings, gc.DeepEquals, settings) 1643 } 1644 1645 func (s *uniterBaseSuite) testJoinedRelations( 1646 c *gc.C, 1647 facade interface { 1648 JoinedRelations(args params.Entities) (params.StringsResults, error) 1649 }, 1650 ) { 1651 rel := s.addRelation(c, "wordpress", "mysql") 1652 relUnit, err := rel.Unit(s.wordpressUnit) 1653 c.Assert(err, jc.ErrorIsNil) 1654 err = relUnit.EnterScope(nil) 1655 c.Assert(err, jc.ErrorIsNil) 1656 1657 args := params.Entities{ 1658 Entities: []params.Entity{ 1659 {s.wordpressUnit.Tag().String()}, 1660 {s.mysqlUnit.Tag().String()}, 1661 {"unit-unknown-1"}, 1662 {"service-wordpress"}, 1663 {"machine-0"}, 1664 {rel.Tag().String()}, 1665 }, 1666 } 1667 expect := params.StringsResults{ 1668 Results: []params.StringsResult{ 1669 {Result: []string{rel.Tag().String()}}, 1670 {Error: apiservertesting.ErrUnauthorized}, 1671 {Error: apiservertesting.ErrUnauthorized}, 1672 {Error: apiservertesting.ErrUnauthorized}, 1673 {Error: apiservertesting.ErrUnauthorized}, 1674 {Error: apiservertesting.ErrUnauthorized}, 1675 }, 1676 } 1677 check := func() { 1678 result, err := facade.JoinedRelations(args) 1679 c.Assert(err, jc.ErrorIsNil) 1680 c.Assert(result, gc.DeepEquals, expect) 1681 } 1682 check() 1683 err = relUnit.PrepareLeaveScope() 1684 c.Assert(err, jc.ErrorIsNil) 1685 check() 1686 } 1687 1688 type readSettings interface { 1689 ReadSettings(args params.RelationUnits) (params.SettingsResults, error) 1690 } 1691 1692 func (s *uniterBaseSuite) testReadSettings(c *gc.C, facade readSettings) { 1693 rel := s.addRelation(c, "wordpress", "mysql") 1694 relUnit, err := rel.Unit(s.wordpressUnit) 1695 c.Assert(err, jc.ErrorIsNil) 1696 settings := map[string]interface{}{ 1697 "some": "settings", 1698 } 1699 err = relUnit.EnterScope(settings) 1700 c.Assert(err, jc.ErrorIsNil) 1701 s.assertInScope(c, relUnit, true) 1702 1703 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1704 {Relation: "relation-42", Unit: "unit-foo-0"}, 1705 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1706 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1707 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1708 {Relation: "relation-foo", Unit: ""}, 1709 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1710 {Relation: "foo", Unit: "bar"}, 1711 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1712 {Relation: rel.Tag().String(), Unit: "service-wordpress"}, 1713 {Relation: rel.Tag().String(), Unit: "service-mysql"}, 1714 {Relation: rel.Tag().String(), Unit: "user-foo"}, 1715 }} 1716 result, err := facade.ReadSettings(args) 1717 c.Assert(err, jc.ErrorIsNil) 1718 c.Assert(result, gc.DeepEquals, params.SettingsResults{ 1719 Results: []params.SettingsResult{ 1720 {Error: apiservertesting.ErrUnauthorized}, 1721 {Settings: params.Settings{ 1722 "some": "settings", 1723 }}, 1724 {Error: apiservertesting.ErrUnauthorized}, 1725 {Error: apiservertesting.ErrUnauthorized}, 1726 {Error: apiservertesting.ErrUnauthorized}, 1727 {Error: apiservertesting.ErrUnauthorized}, 1728 {Error: apiservertesting.ErrUnauthorized}, 1729 {Error: apiservertesting.ErrUnauthorized}, 1730 {Error: apiservertesting.ErrUnauthorized}, 1731 {Error: apiservertesting.ErrUnauthorized}, 1732 {Error: apiservertesting.ErrUnauthorized}, 1733 }, 1734 }) 1735 } 1736 1737 func (s *uniterBaseSuite) testReadSettingsWithNonStringValuesFails(c *gc.C, facade readSettings) { 1738 rel := s.addRelation(c, "wordpress", "mysql") 1739 relUnit, err := rel.Unit(s.wordpressUnit) 1740 c.Assert(err, jc.ErrorIsNil) 1741 settings := map[string]interface{}{ 1742 "other": "things", 1743 "invalid-bool": false, 1744 } 1745 err = relUnit.EnterScope(settings) 1746 c.Assert(err, jc.ErrorIsNil) 1747 s.assertInScope(c, relUnit, true) 1748 1749 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1750 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1751 }} 1752 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool` 1753 result, err := facade.ReadSettings(args) 1754 c.Assert(err, jc.ErrorIsNil) 1755 c.Assert(result, gc.DeepEquals, params.SettingsResults{ 1756 Results: []params.SettingsResult{ 1757 {Error: ¶ms.Error{Message: expectErr}}, 1758 }, 1759 }) 1760 } 1761 1762 type readRemoteSettings interface { 1763 ReadRemoteSettings(args params.RelationUnitPairs) (params.SettingsResults, error) 1764 } 1765 1766 func (s *uniterBaseSuite) testReadRemoteSettings(c *gc.C, facade readRemoteSettings) { 1767 rel := s.addRelation(c, "wordpress", "mysql") 1768 relUnit, err := rel.Unit(s.wordpressUnit) 1769 c.Assert(err, jc.ErrorIsNil) 1770 settings := map[string]interface{}{ 1771 "some": "settings", 1772 } 1773 err = relUnit.EnterScope(settings) 1774 c.Assert(err, jc.ErrorIsNil) 1775 s.assertInScope(c, relUnit, true) 1776 1777 // First test most of the invalid args tests and try to read the 1778 // (unset) remote unit settings. 1779 args := params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{ 1780 {Relation: "relation-42", LocalUnit: "unit-foo-0", RemoteUnit: "foo"}, 1781 {Relation: rel.Tag().String(), LocalUnit: "unit-wordpress-0", RemoteUnit: "unit-wordpress-0"}, 1782 {Relation: rel.Tag().String(), LocalUnit: "unit-wordpress-0", RemoteUnit: "unit-mysql-0"}, 1783 {Relation: "relation-42", LocalUnit: "unit-wordpress-0", RemoteUnit: ""}, 1784 {Relation: "relation-foo", LocalUnit: "", RemoteUnit: ""}, 1785 {Relation: "service-wordpress", LocalUnit: "unit-foo-0", RemoteUnit: "user-foo"}, 1786 {Relation: "foo", LocalUnit: "bar", RemoteUnit: "baz"}, 1787 {Relation: rel.Tag().String(), LocalUnit: "unit-mysql-0", RemoteUnit: "unit-wordpress-0"}, 1788 {Relation: rel.Tag().String(), LocalUnit: "service-wordpress", RemoteUnit: "service-mysql"}, 1789 {Relation: rel.Tag().String(), LocalUnit: "service-mysql", RemoteUnit: "foo"}, 1790 {Relation: rel.Tag().String(), LocalUnit: "user-foo", RemoteUnit: "unit-wordpress-0"}, 1791 }} 1792 result, err := facade.ReadRemoteSettings(args) 1793 1794 // We don't set the remote unit settings on purpose to test the error. 1795 expectErr := `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings` 1796 c.Assert(err, jc.ErrorIsNil) 1797 c.Assert(result, jc.DeepEquals, params.SettingsResults{ 1798 Results: []params.SettingsResult{ 1799 {Error: apiservertesting.ErrUnauthorized}, 1800 {Error: apiservertesting.ErrUnauthorized}, 1801 {Error: apiservertesting.NotFoundError(expectErr)}, 1802 {Error: apiservertesting.ErrUnauthorized}, 1803 {Error: apiservertesting.ErrUnauthorized}, 1804 {Error: apiservertesting.ErrUnauthorized}, 1805 {Error: apiservertesting.ErrUnauthorized}, 1806 {Error: apiservertesting.ErrUnauthorized}, 1807 {Error: apiservertesting.ErrUnauthorized}, 1808 {Error: apiservertesting.ErrUnauthorized}, 1809 {Error: apiservertesting.ErrUnauthorized}, 1810 }, 1811 }) 1812 1813 // Now leave the mysqlUnit and re-enter with new settings. 1814 relUnit, err = rel.Unit(s.mysqlUnit) 1815 c.Assert(err, jc.ErrorIsNil) 1816 settings = map[string]interface{}{ 1817 "other": "things", 1818 } 1819 err = relUnit.LeaveScope() 1820 c.Assert(err, jc.ErrorIsNil) 1821 s.assertInScope(c, relUnit, false) 1822 err = relUnit.EnterScope(settings) 1823 c.Assert(err, jc.ErrorIsNil) 1824 s.assertInScope(c, relUnit, true) 1825 1826 // Test the remote unit settings can be read. 1827 args = params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{{ 1828 Relation: rel.Tag().String(), 1829 LocalUnit: "unit-wordpress-0", 1830 RemoteUnit: "unit-mysql-0", 1831 }}} 1832 expect := params.SettingsResults{ 1833 Results: []params.SettingsResult{ 1834 {Settings: params.Settings{ 1835 "other": "things", 1836 }}, 1837 }, 1838 } 1839 result, err = facade.ReadRemoteSettings(args) 1840 c.Assert(err, jc.ErrorIsNil) 1841 c.Assert(result, gc.DeepEquals, expect) 1842 1843 // Now destroy the remote unit, and check its settings can still be read. 1844 err = s.mysqlUnit.Destroy() 1845 c.Assert(err, jc.ErrorIsNil) 1846 err = s.mysqlUnit.EnsureDead() 1847 c.Assert(err, jc.ErrorIsNil) 1848 err = s.mysqlUnit.Remove() 1849 c.Assert(err, jc.ErrorIsNil) 1850 result, err = facade.ReadRemoteSettings(args) 1851 c.Assert(err, jc.ErrorIsNil) 1852 c.Assert(result, gc.DeepEquals, expect) 1853 } 1854 1855 func (s *uniterBaseSuite) testReadRemoteSettingsWithNonStringValuesFails(c *gc.C, facade readRemoteSettings) { 1856 rel := s.addRelation(c, "wordpress", "mysql") 1857 relUnit, err := rel.Unit(s.mysqlUnit) 1858 c.Assert(err, jc.ErrorIsNil) 1859 settings := map[string]interface{}{ 1860 "other": "things", 1861 "invalid-bool": false, 1862 } 1863 err = relUnit.EnterScope(settings) 1864 c.Assert(err, jc.ErrorIsNil) 1865 s.assertInScope(c, relUnit, true) 1866 1867 args := params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{{ 1868 Relation: rel.Tag().String(), 1869 LocalUnit: "unit-wordpress-0", 1870 RemoteUnit: "unit-mysql-0", 1871 }}} 1872 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool` 1873 result, err := facade.ReadRemoteSettings(args) 1874 c.Assert(err, jc.ErrorIsNil) 1875 c.Assert(result, gc.DeepEquals, params.SettingsResults{ 1876 Results: []params.SettingsResult{ 1877 {Error: ¶ms.Error{Message: expectErr}}, 1878 }, 1879 }) 1880 } 1881 1882 func (s *uniterBaseSuite) testUpdateSettings( 1883 c *gc.C, 1884 facade interface { 1885 UpdateSettings(args params.RelationUnitsSettings) (params.ErrorResults, error) 1886 }, 1887 ) { 1888 rel := s.addRelation(c, "wordpress", "mysql") 1889 relUnit, err := rel.Unit(s.wordpressUnit) 1890 c.Assert(err, jc.ErrorIsNil) 1891 settings := map[string]interface{}{ 1892 "some": "settings", 1893 "other": "stuff", 1894 } 1895 err = relUnit.EnterScope(settings) 1896 s.assertInScope(c, relUnit, true) 1897 1898 newSettings := params.Settings{ 1899 "some": "different", 1900 "other": "", 1901 } 1902 1903 args := params.RelationUnitsSettings{RelationUnits: []params.RelationUnitSettings{ 1904 {Relation: "relation-42", Unit: "unit-foo-0", Settings: nil}, 1905 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0", Settings: newSettings}, 1906 {Relation: "relation-42", Unit: "unit-wordpress-0", Settings: nil}, 1907 {Relation: "relation-foo", Unit: "unit-wordpress-0", Settings: nil}, 1908 {Relation: "service-wordpress", Unit: "unit-foo-0", Settings: nil}, 1909 {Relation: "foo", Unit: "bar", Settings: nil}, 1910 {Relation: rel.Tag().String(), Unit: "unit-mysql-0", Settings: nil}, 1911 {Relation: rel.Tag().String(), Unit: "service-wordpress", Settings: nil}, 1912 {Relation: rel.Tag().String(), Unit: "service-mysql", Settings: nil}, 1913 {Relation: rel.Tag().String(), Unit: "user-foo", Settings: nil}, 1914 }} 1915 result, err := facade.UpdateSettings(args) 1916 c.Assert(err, jc.ErrorIsNil) 1917 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 1918 Results: []params.ErrorResult{ 1919 {apiservertesting.ErrUnauthorized}, 1920 {nil}, 1921 {apiservertesting.ErrUnauthorized}, 1922 {apiservertesting.ErrUnauthorized}, 1923 {apiservertesting.ErrUnauthorized}, 1924 {apiservertesting.ErrUnauthorized}, 1925 {apiservertesting.ErrUnauthorized}, 1926 {apiservertesting.ErrUnauthorized}, 1927 {apiservertesting.ErrUnauthorized}, 1928 {apiservertesting.ErrUnauthorized}, 1929 }, 1930 }) 1931 1932 // Verify the settings were saved. 1933 s.assertInScope(c, relUnit, true) 1934 readSettings, err := relUnit.ReadSettings(s.wordpressUnit.Name()) 1935 c.Assert(err, jc.ErrorIsNil) 1936 c.Assert(readSettings, gc.DeepEquals, map[string]interface{}{ 1937 "some": "different", 1938 }) 1939 } 1940 1941 func (s *uniterBaseSuite) testWatchRelationUnits( 1942 c *gc.C, 1943 facade interface { 1944 WatchRelationUnits(args params.RelationUnits) (params.RelationUnitsWatchResults, error) 1945 }, 1946 ) { 1947 // Add a relation between wordpress and mysql and enter scope with 1948 // mysqlUnit. 1949 rel := s.addRelation(c, "wordpress", "mysql") 1950 myRelUnit, err := rel.Unit(s.mysqlUnit) 1951 c.Assert(err, jc.ErrorIsNil) 1952 err = myRelUnit.EnterScope(nil) 1953 c.Assert(err, jc.ErrorIsNil) 1954 s.assertInScope(c, myRelUnit, true) 1955 1956 c.Assert(s.resources.Count(), gc.Equals, 0) 1957 1958 args := params.RelationUnits{RelationUnits: []params.RelationUnit{ 1959 {Relation: "relation-42", Unit: "unit-foo-0"}, 1960 {Relation: rel.Tag().String(), Unit: "unit-wordpress-0"}, 1961 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1962 {Relation: "relation-42", Unit: "unit-wordpress-0"}, 1963 {Relation: "relation-foo", Unit: ""}, 1964 {Relation: "service-wordpress", Unit: "unit-foo-0"}, 1965 {Relation: "foo", Unit: "bar"}, 1966 {Relation: rel.Tag().String(), Unit: "unit-mysql-0"}, 1967 {Relation: rel.Tag().String(), Unit: "service-wordpress"}, 1968 {Relation: rel.Tag().String(), Unit: "service-mysql"}, 1969 {Relation: rel.Tag().String(), Unit: "user-foo"}, 1970 }} 1971 result, err := facade.WatchRelationUnits(args) 1972 c.Assert(err, jc.ErrorIsNil) 1973 // UnitSettings versions are volatile, so we don't check them. 1974 // We just make sure the keys of the Changed field are as 1975 // expected. 1976 c.Assert(result.Results, gc.HasLen, len(args.RelationUnits)) 1977 mysqlChanges := result.Results[1].Changes 1978 c.Assert(mysqlChanges, gc.NotNil) 1979 changed, ok := mysqlChanges.Changed["mysql/0"] 1980 c.Assert(ok, jc.IsTrue) 1981 expectChanges := multiwatcher.RelationUnitsChange{ 1982 Changed: map[string]multiwatcher.UnitSettings{"mysql/0": changed}, 1983 } 1984 c.Assert(result, gc.DeepEquals, params.RelationUnitsWatchResults{ 1985 Results: []params.RelationUnitsWatchResult{ 1986 {Error: apiservertesting.ErrUnauthorized}, 1987 { 1988 RelationUnitsWatcherId: "1", 1989 Changes: expectChanges, 1990 }, 1991 {Error: apiservertesting.ErrUnauthorized}, 1992 {Error: apiservertesting.ErrUnauthorized}, 1993 {Error: apiservertesting.ErrUnauthorized}, 1994 {Error: apiservertesting.ErrUnauthorized}, 1995 {Error: apiservertesting.ErrUnauthorized}, 1996 {Error: apiservertesting.ErrUnauthorized}, 1997 {Error: apiservertesting.ErrUnauthorized}, 1998 {Error: apiservertesting.ErrUnauthorized}, 1999 {Error: apiservertesting.ErrUnauthorized}, 2000 }, 2001 }) 2002 2003 // Verify the resource was registered and stop when done 2004 c.Assert(s.resources.Count(), gc.Equals, 1) 2005 resource := s.resources.Get("1") 2006 defer statetesting.AssertStop(c, resource) 2007 2008 // Check that the Watch has consumed the initial event ("returned" in 2009 // the Watch call) 2010 wc := statetesting.NewRelationUnitsWatcherC(c, s.State, resource.(state.RelationUnitsWatcher)) 2011 wc.AssertNoChange() 2012 2013 // Leave scope with mysqlUnit and check it's detected. 2014 err = myRelUnit.LeaveScope() 2015 c.Assert(err, jc.ErrorIsNil) 2016 s.assertInScope(c, myRelUnit, false) 2017 2018 wc.AssertChange(nil, []string{"mysql/0"}) 2019 } 2020 2021 func (s *uniterBaseSuite) testAPIAddresses( 2022 c *gc.C, 2023 facade interface { 2024 APIAddresses() (params.StringsResult, error) 2025 }, 2026 ) { 2027 hostPorts := [][]network.HostPort{{{ 2028 Address: network.NewAddress("0.1.2.3", network.ScopeUnknown), 2029 Port: 1234, 2030 }}} 2031 2032 err := s.State.SetAPIHostPorts(hostPorts) 2033 c.Assert(err, jc.ErrorIsNil) 2034 2035 result, err := facade.APIAddresses() 2036 c.Assert(err, jc.ErrorIsNil) 2037 c.Assert(result, gc.DeepEquals, params.StringsResult{ 2038 Result: []string{"0.1.2.3:1234"}, 2039 }) 2040 } 2041 2042 func (s *uniterBaseSuite) testWatchUnitAddresses( 2043 c *gc.C, 2044 facade interface { 2045 WatchUnitAddresses(args params.Entities) (params.NotifyWatchResults, error) 2046 }, 2047 ) { 2048 c.Assert(s.resources.Count(), gc.Equals, 0) 2049 2050 args := params.Entities{Entities: []params.Entity{ 2051 {Tag: "unit-mysql-0"}, 2052 {Tag: "unit-wordpress-0"}, 2053 {Tag: "unit-foo-42"}, 2054 {Tag: "machine-0"}, 2055 {Tag: "service-wordpress"}, 2056 }} 2057 result, err := facade.WatchUnitAddresses(args) 2058 c.Assert(err, jc.ErrorIsNil) 2059 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 2060 Results: []params.NotifyWatchResult{ 2061 {Error: apiservertesting.ErrUnauthorized}, 2062 {NotifyWatcherId: "1"}, 2063 {Error: apiservertesting.ErrUnauthorized}, 2064 {Error: apiservertesting.ErrUnauthorized}, 2065 {Error: apiservertesting.ErrUnauthorized}, 2066 }, 2067 }) 2068 2069 // Verify the resource was registered and stop when done 2070 c.Assert(s.resources.Count(), gc.Equals, 1) 2071 resource := s.resources.Get("1") 2072 defer statetesting.AssertStop(c, resource) 2073 2074 // Check that the Watch has consumed the initial event ("returned" in 2075 // the Watch call) 2076 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 2077 wc.AssertNoChange() 2078 } 2079 2080 type addMetrics interface { 2081 AddMetrics(args params.MetricsParams) (params.ErrorResults, error) 2082 } 2083 2084 func (s *uniterBaseSuite) testAddMetrics(c *gc.C, facade addMetrics) { 2085 now := time.Now() 2086 sentMetrics := []params.Metric{{"pings", "5", now}, {"juju-unit-time", "0.71", now}} 2087 args := params.MetricsParams{ 2088 Metrics: []params.MetricsParam{{ 2089 Tag: s.meteredUnit.Tag().String(), 2090 Metrics: sentMetrics, 2091 }}, 2092 } 2093 result, err := facade.AddMetrics(args) 2094 c.Assert(err, jc.ErrorIsNil) 2095 c.Assert(result.Results, gc.HasLen, 1) 2096 c.Assert(result.Results[0].Error, gc.IsNil) 2097 2098 metrics, err := s.State.MetricBatches() 2099 c.Assert(err, jc.ErrorIsNil) 2100 c.Assert(metrics, gc.HasLen, 1) 2101 2102 unitMetrics := metrics[0].Metrics() 2103 c.Assert(unitMetrics, gc.HasLen, 2) 2104 2105 for i, unitMetric := range unitMetrics { 2106 c.Assert(unitMetric.Key, gc.Equals, sentMetrics[i].Key) 2107 c.Assert(unitMetric.Value, gc.Equals, sentMetrics[i].Value) 2108 } 2109 } 2110 2111 func (s *uniterBaseSuite) testAddMetricsIncorrectTag(c *gc.C, facade addMetrics) { 2112 now := time.Now() 2113 2114 tags := []string{"user-admin", "unit-nosuchunit", "thisisnotatag", "machine-0", "environment-blah"} 2115 2116 for _, tag := range tags { 2117 2118 args := params.MetricsParams{ 2119 Metrics: []params.MetricsParam{{ 2120 Tag: tag, 2121 Metrics: []params.Metric{{"A", "5", now}, {"B", "0.71", now}}, 2122 }}, 2123 } 2124 2125 result, err := facade.AddMetrics(args) 2126 c.Assert(err, jc.ErrorIsNil) 2127 c.Assert(result.Results, gc.HasLen, 1) 2128 c.Assert(result.Results[0].Error, gc.ErrorMatches, "permission denied") 2129 metrics, err := s.State.MetricBatches() 2130 c.Assert(err, jc.ErrorIsNil) 2131 c.Assert(metrics, gc.HasLen, 0) 2132 } 2133 } 2134 2135 func (s *uniterBaseSuite) testAddMetricsUnauthenticated(c *gc.C, facade addMetrics) { 2136 now := time.Now() 2137 args := params.MetricsParams{ 2138 Metrics: []params.MetricsParam{{ 2139 Tag: s.mysqlUnit.Tag().String(), 2140 Metrics: []params.Metric{{"A", "5", now}, {"B", "0.71", now}}, 2141 }}, 2142 } 2143 result, err := facade.AddMetrics(args) 2144 c.Assert(err, jc.ErrorIsNil) 2145 c.Assert(result.Results, gc.HasLen, 1) 2146 c.Assert(result.Results[0].Error, gc.ErrorMatches, "permission denied") 2147 metrics, err := s.State.MetricBatches() 2148 c.Assert(err, jc.ErrorIsNil) 2149 c.Assert(metrics, gc.HasLen, 0) 2150 } 2151 2152 type getMeterStatus interface { 2153 GetMeterStatus(args params.Entities) (params.MeterStatusResults, error) 2154 } 2155 2156 func (s *uniterBaseSuite) testGetMeterStatus(c *gc.C, facade getMeterStatus) { 2157 args := params.Entities{Entities: []params.Entity{{Tag: s.wordpressUnit.Tag().String()}}} 2158 result, err := facade.GetMeterStatus(args) 2159 c.Assert(err, jc.ErrorIsNil) 2160 c.Assert(result.Results, gc.HasLen, 1) 2161 c.Assert(result.Results[0].Error, gc.IsNil) 2162 c.Assert(result.Results[0].Code, gc.Equals, "NOT SET") 2163 c.Assert(result.Results[0].Info, gc.Equals, "") 2164 2165 newCode := "GREEN" 2166 newInfo := "All is ok." 2167 2168 err = s.wordpressUnit.SetMeterStatus(newCode, newInfo) 2169 c.Assert(err, jc.ErrorIsNil) 2170 2171 result, err = facade.GetMeterStatus(args) 2172 c.Assert(err, jc.ErrorIsNil) 2173 c.Assert(result.Results, gc.HasLen, 1) 2174 c.Assert(result.Results[0].Error, gc.IsNil) 2175 c.Assert(result.Results[0].Code, gc.DeepEquals, newCode) 2176 c.Assert(result.Results[0].Info, gc.DeepEquals, newInfo) 2177 } 2178 2179 func (s *uniterBaseSuite) testGetMeterStatusUnauthenticated(c *gc.C, facade getMeterStatus) { 2180 args := params.Entities{Entities: []params.Entity{{s.mysqlUnit.Tag().String()}}} 2181 result, err := facade.GetMeterStatus(args) 2182 c.Assert(err, jc.ErrorIsNil) 2183 c.Assert(result.Results, gc.HasLen, 1) 2184 c.Assert(result.Results[0].Error, gc.ErrorMatches, "permission denied") 2185 c.Assert(result.Results[0].Code, gc.Equals, "") 2186 c.Assert(result.Results[0].Info, gc.Equals, "") 2187 } 2188 2189 func (s *uniterBaseSuite) testGetMeterStatusBadTag(c *gc.C, facade getMeterStatus) { 2190 tags := []string{ 2191 "user-admin", 2192 "unit-nosuchunit", 2193 "thisisnotatag", 2194 "machine-0", 2195 "environment-blah", 2196 } 2197 args := params.Entities{Entities: make([]params.Entity, len(tags))} 2198 for i, tag := range tags { 2199 args.Entities[i] = params.Entity{Tag: tag} 2200 } 2201 result, err := facade.GetMeterStatus(args) 2202 c.Assert(err, jc.ErrorIsNil) 2203 c.Assert(result.Results, gc.HasLen, len(tags)) 2204 for i, result := range result.Results { 2205 c.Logf("checking result %d", i) 2206 c.Assert(result.Code, gc.Equals, "") 2207 c.Assert(result.Info, gc.Equals, "") 2208 c.Assert(result.Error, gc.ErrorMatches, "permission denied") 2209 } 2210 } 2211 2212 func (s *uniterBaseSuite) testWatchMeterStatus( 2213 c *gc.C, 2214 facade interface { 2215 WatchMeterStatus(args params.Entities) (params.NotifyWatchResults, error) 2216 }, 2217 ) { 2218 c.Assert(s.resources.Count(), gc.Equals, 0) 2219 2220 args := params.Entities{Entities: []params.Entity{ 2221 {Tag: "unit-mysql-0"}, 2222 {Tag: "unit-wordpress-0"}, 2223 {Tag: "unit-foo-42"}, 2224 }} 2225 result, err := facade.WatchMeterStatus(args) 2226 c.Assert(err, jc.ErrorIsNil) 2227 c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ 2228 Results: []params.NotifyWatchResult{ 2229 {Error: apiservertesting.ErrUnauthorized}, 2230 {NotifyWatcherId: "1"}, 2231 {Error: apiservertesting.ErrUnauthorized}, 2232 }, 2233 }) 2234 2235 // Verify the resource was registered and stop when done 2236 c.Assert(s.resources.Count(), gc.Equals, 1) 2237 resource := s.resources.Get("1") 2238 defer statetesting.AssertStop(c, resource) 2239 2240 // Check that the Watch has consumed the initial event ("returned" in 2241 // the Watch call) 2242 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 2243 wc.AssertNoChange() 2244 2245 err = s.wordpressUnit.SetMeterStatus("GREEN", "No additional information.") 2246 wc.AssertOneChange() 2247 } 2248 2249 func (s *uniterBaseSuite) assertOneStringsWatcher(c *gc.C, result params.StringsWatchResults, err error) { 2250 c.Assert(err, jc.ErrorIsNil) 2251 c.Assert(result.Results, gc.HasLen, 3) 2252 c.Assert(result.Results[0].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 2253 c.Assert(result.Results[1].StringsWatcherId, gc.Equals, "1") 2254 c.Assert(result.Results[1].Changes, gc.NotNil) 2255 c.Assert(result.Results[1].Error, gc.IsNil) 2256 c.Assert(result.Results[2].Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 2257 2258 // Verify the resource was registered and stop when done 2259 c.Assert(s.resources.Count(), gc.Equals, 1) 2260 resource := s.resources.Get("1") 2261 defer statetesting.AssertStop(c, resource) 2262 2263 // Check that the Watch has consumed the initial event ("returned" in 2264 // the Watch call) 2265 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 2266 wc.AssertNoChange() 2267 } 2268 2269 func (s *uniterBaseSuite) assertInScope(c *gc.C, relUnit *state.RelationUnit, inScope bool) { 2270 ok, err := relUnit.InScope() 2271 c.Assert(err, jc.ErrorIsNil) 2272 c.Assert(ok, gc.Equals, inScope) 2273 } 2274 2275 func (s *uniterBaseSuite) addRelation(c *gc.C, first, second string) *state.Relation { 2276 eps, err := s.State.InferEndpoints(first, second) 2277 c.Assert(err, jc.ErrorIsNil) 2278 rel, err := s.State.AddRelation(eps...) 2279 c.Assert(err, jc.ErrorIsNil) 2280 return rel 2281 } 2282 2283 func (s *uniterBaseSuite) addRelatedService(c *gc.C, firstSvc, relatedSvc string, unit *state.Unit) (*state.Relation, *state.Service, *state.Unit) { 2284 relatedService := s.AddTestingService(c, relatedSvc, s.AddTestingCharm(c, relatedSvc)) 2285 rel := s.addRelation(c, firstSvc, relatedSvc) 2286 relUnit, err := rel.Unit(unit) 2287 c.Assert(err, jc.ErrorIsNil) 2288 err = relUnit.EnterScope(nil) 2289 c.Assert(err, jc.ErrorIsNil) 2290 relatedUnit, err := s.State.Unit(relatedSvc + "/0") 2291 c.Assert(err, jc.ErrorIsNil) 2292 return rel, relatedService, relatedUnit 2293 } 2294 2295 func checkUnorderedActionIdsEqual(c *gc.C, ids []string, results params.StringsWatchResults) { 2296 c.Assert(results, gc.NotNil) 2297 content := results.Results 2298 c.Assert(len(content), gc.Equals, 1) 2299 result := content[0] 2300 c.Assert(result.StringsWatcherId, gc.Equals, "1") 2301 obtainedIds := map[string]int{} 2302 expectedIds := map[string]int{} 2303 for _, id := range ids { 2304 expectedIds[id]++ 2305 } 2306 // The count of each ID that has been seen. 2307 for _, change := range result.Changes { 2308 obtainedIds[change]++ 2309 } 2310 c.Check(obtainedIds, jc.DeepEquals, expectedIds) 2311 }