github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/uniter/unit_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 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/juju/charm.v6-unstable" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/api" 18 "github.com/juju/juju/api/base" 19 "github.com/juju/juju/api/uniter" 20 "github.com/juju/juju/apiserver/common" 21 "github.com/juju/juju/apiserver/params" 22 "github.com/juju/juju/juju/testing" 23 "github.com/juju/juju/network" 24 "github.com/juju/juju/state" 25 "github.com/juju/juju/status" 26 jujufactory "github.com/juju/juju/testing/factory" 27 "github.com/juju/juju/watcher/watchertest" 28 ) 29 30 type unitSuite struct { 31 uniterSuite 32 33 apiUnit *uniter.Unit 34 } 35 36 var _ = gc.Suite(&unitSuite{}) 37 38 func (s *unitSuite) SetUpTest(c *gc.C) { 39 s.uniterSuite.SetUpTest(c) 40 41 var err error 42 s.apiUnit, err = s.uniter.Unit(s.wordpressUnit.Tag().(names.UnitTag)) 43 c.Assert(err, jc.ErrorIsNil) 44 } 45 46 func (s *unitSuite) TestRequestReboot(c *gc.C) { 47 err := s.apiUnit.RequestReboot() 48 c.Assert(err, jc.ErrorIsNil) 49 rFlag, err := s.wordpressMachine.GetRebootFlag() 50 c.Assert(err, jc.ErrorIsNil) 51 c.Assert(rFlag, jc.IsTrue) 52 } 53 54 func (s *unitSuite) TestUnitAndUnitTag(c *gc.C) { 55 apiUnitFoo, err := s.uniter.Unit(names.NewUnitTag("foo/42")) 56 c.Assert(err, gc.ErrorMatches, "permission denied") 57 c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized) 58 c.Assert(apiUnitFoo, gc.IsNil) 59 60 c.Assert(s.apiUnit.Tag(), gc.Equals, s.wordpressUnit.Tag().(names.UnitTag)) 61 } 62 63 func (s *unitSuite) TestSetAgentStatus(c *gc.C) { 64 statusInfo, err := s.wordpressUnit.AgentStatus() 65 c.Assert(err, jc.ErrorIsNil) 66 c.Assert(statusInfo.Status, gc.Equals, status.Allocating) 67 c.Assert(statusInfo.Message, gc.Equals, "") 68 c.Assert(statusInfo.Data, gc.HasLen, 0) 69 70 unitStatusInfo, err := s.wordpressUnit.Status() 71 c.Assert(err, jc.ErrorIsNil) 72 c.Assert(unitStatusInfo.Status, gc.Equals, status.Waiting) 73 c.Assert(unitStatusInfo.Message, gc.Equals, "waiting for machine") 74 c.Assert(unitStatusInfo.Data, gc.HasLen, 0) 75 76 err = s.apiUnit.SetAgentStatus(status.Idle, "blah", nil) 77 c.Assert(err, jc.ErrorIsNil) 78 79 statusInfo, err = s.wordpressUnit.AgentStatus() 80 c.Assert(err, jc.ErrorIsNil) 81 c.Assert(statusInfo.Status, gc.Equals, status.Idle) 82 c.Assert(statusInfo.Message, gc.Equals, "blah") 83 c.Assert(statusInfo.Data, gc.HasLen, 0) 84 c.Assert(statusInfo.Since, gc.NotNil) 85 86 // Ensure that unit has not changed. 87 unitStatusInfo, err = s.wordpressUnit.Status() 88 c.Assert(err, jc.ErrorIsNil) 89 c.Assert(unitStatusInfo.Status, gc.Equals, status.Waiting) 90 c.Assert(unitStatusInfo.Message, gc.Equals, "waiting for machine") 91 c.Assert(unitStatusInfo.Data, gc.HasLen, 0) 92 } 93 94 func (s *unitSuite) TestSetUnitStatus(c *gc.C) { 95 statusInfo, err := s.wordpressUnit.Status() 96 c.Assert(err, jc.ErrorIsNil) 97 c.Assert(statusInfo.Status, gc.Equals, status.Waiting) 98 c.Assert(statusInfo.Message, gc.Equals, "waiting for machine") 99 c.Assert(statusInfo.Data, gc.HasLen, 0) 100 101 agentStatusInfo, err := s.wordpressUnit.AgentStatus() 102 c.Assert(err, jc.ErrorIsNil) 103 c.Assert(agentStatusInfo.Status, gc.Equals, status.Allocating) 104 c.Assert(agentStatusInfo.Message, gc.Equals, "") 105 c.Assert(agentStatusInfo.Data, gc.HasLen, 0) 106 107 err = s.apiUnit.SetUnitStatus(status.Active, "blah", nil) 108 c.Assert(err, jc.ErrorIsNil) 109 110 statusInfo, err = s.wordpressUnit.Status() 111 c.Assert(err, jc.ErrorIsNil) 112 c.Assert(statusInfo.Status, gc.Equals, status.Active) 113 c.Assert(statusInfo.Message, gc.Equals, "blah") 114 c.Assert(statusInfo.Data, gc.HasLen, 0) 115 c.Assert(statusInfo.Since, gc.NotNil) 116 117 // Ensure unit's agent has not changed. 118 agentStatusInfo, err = s.wordpressUnit.AgentStatus() 119 c.Assert(err, jc.ErrorIsNil) 120 c.Assert(agentStatusInfo.Status, gc.Equals, status.Allocating) 121 c.Assert(agentStatusInfo.Message, gc.Equals, "") 122 c.Assert(agentStatusInfo.Data, gc.HasLen, 0) 123 } 124 125 func (s *unitSuite) TestUnitStatus(c *gc.C) { 126 now := time.Now() 127 sInfo := status.StatusInfo{ 128 Status: status.Maintenance, 129 Message: "blah", 130 Since: &now, 131 } 132 err := s.wordpressUnit.SetStatus(sInfo) 133 c.Assert(err, jc.ErrorIsNil) 134 135 result, err := s.apiUnit.UnitStatus() 136 c.Assert(err, jc.ErrorIsNil) 137 c.Assert(result.Since, gc.NotNil) 138 result.Since = nil 139 c.Assert(result, gc.DeepEquals, params.StatusResult{ 140 Status: status.Maintenance.String(), 141 Info: "blah", 142 Data: map[string]interface{}{}, 143 }) 144 } 145 146 func (s *unitSuite) TestEnsureDead(c *gc.C) { 147 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 148 149 err := s.apiUnit.EnsureDead() 150 c.Assert(err, jc.ErrorIsNil) 151 152 err = s.wordpressUnit.Refresh() 153 c.Assert(err, jc.ErrorIsNil) 154 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 155 156 err = s.apiUnit.EnsureDead() 157 c.Assert(err, jc.ErrorIsNil) 158 err = s.wordpressUnit.Refresh() 159 c.Assert(err, jc.ErrorIsNil) 160 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Dead) 161 162 err = s.wordpressUnit.Remove() 163 c.Assert(err, jc.ErrorIsNil) 164 err = s.wordpressUnit.Refresh() 165 c.Assert(err, jc.Satisfies, errors.IsNotFound) 166 167 err = s.apiUnit.EnsureDead() 168 c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`) 169 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 170 } 171 172 func (s *unitSuite) TestDestroy(c *gc.C) { 173 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 174 175 err := s.apiUnit.Destroy() 176 c.Assert(err, jc.ErrorIsNil) 177 178 err = s.wordpressUnit.Refresh() 179 c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`) 180 } 181 182 func (s *unitSuite) TestDestroyAllSubordinates(c *gc.C) { 183 c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive) 184 185 // Call without subordinates - no change. 186 err := s.apiUnit.DestroyAllSubordinates() 187 c.Assert(err, jc.ErrorIsNil) 188 189 // Add a couple of subordinates and try again. 190 _, _, loggingSub := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 191 _, _, monitoringSub := s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 192 c.Assert(loggingSub.Life(), gc.Equals, state.Alive) 193 c.Assert(monitoringSub.Life(), gc.Equals, state.Alive) 194 195 err = s.apiUnit.DestroyAllSubordinates() 196 c.Assert(err, jc.ErrorIsNil) 197 198 // Verify they got destroyed. 199 err = loggingSub.Refresh() 200 c.Assert(err, jc.ErrorIsNil) 201 c.Assert(loggingSub.Life(), gc.Equals, state.Dying) 202 err = monitoringSub.Refresh() 203 c.Assert(err, jc.ErrorIsNil) 204 c.Assert(monitoringSub.Life(), gc.Equals, state.Dying) 205 } 206 207 func (s *unitSuite) TestRefresh(c *gc.C) { 208 c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive) 209 210 err := s.apiUnit.EnsureDead() 211 c.Assert(err, jc.ErrorIsNil) 212 c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive) 213 214 err = s.apiUnit.Refresh() 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(s.apiUnit.Life(), gc.Equals, params.Dead) 217 } 218 219 func (s *unitSuite) TestWatch(c *gc.C) { 220 c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive) 221 222 w, err := s.apiUnit.Watch() 223 c.Assert(err, jc.ErrorIsNil) 224 wc := watchertest.NewNotifyWatcherC(c, w, s.BackingState.StartSync) 225 defer wc.AssertStops() 226 227 // Initial event. 228 wc.AssertOneChange() 229 230 // Change something other than the lifecycle and make sure it's 231 // not detected. 232 err = s.apiUnit.SetAgentStatus(status.Idle, "not really", nil) 233 c.Assert(err, jc.ErrorIsNil) 234 wc.AssertNoChange() 235 236 // Make the unit dead and check it's detected. 237 err = s.apiUnit.EnsureDead() 238 c.Assert(err, jc.ErrorIsNil) 239 wc.AssertOneChange() 240 } 241 242 func (s *unitSuite) TestResolve(c *gc.C) { 243 err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks) 244 c.Assert(err, jc.ErrorIsNil) 245 246 mode, err := s.apiUnit.Resolved() 247 c.Assert(err, jc.ErrorIsNil) 248 c.Assert(mode, gc.Equals, params.ResolvedRetryHooks) 249 250 err = s.apiUnit.ClearResolved() 251 c.Assert(err, jc.ErrorIsNil) 252 253 mode, err = s.apiUnit.Resolved() 254 c.Assert(err, jc.ErrorIsNil) 255 c.Assert(mode, gc.Equals, params.ResolvedNone) 256 } 257 258 func (s *unitSuite) TestAssignedMachine(c *gc.C) { 259 machineTag, err := s.apiUnit.AssignedMachine() 260 c.Assert(err, jc.ErrorIsNil) 261 c.Assert(machineTag, gc.Equals, s.wordpressMachine.Tag()) 262 } 263 264 func (s *unitSuite) TestIsPrincipal(c *gc.C) { 265 ok, err := s.apiUnit.IsPrincipal() 266 c.Assert(err, jc.ErrorIsNil) 267 c.Assert(ok, jc.IsTrue) 268 } 269 270 func (s *unitSuite) TestHasSubordinates(c *gc.C) { 271 found, err := s.apiUnit.HasSubordinates() 272 c.Assert(err, jc.ErrorIsNil) 273 c.Assert(found, jc.IsFalse) 274 275 // Add a couple of subordinates and try again. 276 s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 277 s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 278 279 found, err = s.apiUnit.HasSubordinates() 280 c.Assert(err, jc.ErrorIsNil) 281 c.Assert(found, jc.IsTrue) 282 } 283 284 func (s *unitSuite) TestPublicAddress(c *gc.C) { 285 address, err := s.apiUnit.PublicAddress() 286 c.Assert(err, gc.ErrorMatches, `"unit-wordpress-0" has no public address set`) 287 288 err = s.wordpressMachine.SetProviderAddresses( 289 network.NewScopedAddress("1.2.3.4", network.ScopePublic), 290 ) 291 c.Assert(err, jc.ErrorIsNil) 292 293 address, err = s.apiUnit.PublicAddress() 294 c.Assert(err, jc.ErrorIsNil) 295 c.Assert(address, gc.Equals, "1.2.3.4") 296 } 297 298 func (s *unitSuite) TestPrivateAddress(c *gc.C) { 299 address, err := s.apiUnit.PrivateAddress() 300 c.Assert(err, gc.ErrorMatches, `"unit-wordpress-0" has no private address set`) 301 302 err = s.wordpressMachine.SetProviderAddresses( 303 network.NewScopedAddress("1.2.3.4", network.ScopeCloudLocal), 304 ) 305 c.Assert(err, jc.ErrorIsNil) 306 307 address, err = s.apiUnit.PrivateAddress() 308 c.Assert(err, jc.ErrorIsNil) 309 c.Assert(address, gc.Equals, "1.2.3.4") 310 } 311 312 func (s *unitSuite) TestNetworkConfig(c *gc.C) { 313 c.Skip("dimitern: temporarily disabled to pass a CI run until it can be fixed like its apiserver/uniter counterpart") 314 315 // Set some provider addresses bound to both "public" and "internal" 316 // spaces. 317 addresses := []network.Address{ 318 network.NewAddressOnSpace("public", "8.8.8.8"), 319 network.NewAddressOnSpace("", "8.8.4.4"), 320 network.NewAddressOnSpace("internal", "10.0.0.1"), 321 network.NewAddressOnSpace("internal", "10.0.0.2"), 322 network.NewAddressOnSpace("public", "fc00::1"), 323 } 324 err := s.wordpressMachine.SetProviderAddresses(addresses...) 325 c.Assert(err, jc.ErrorIsNil) 326 327 netConfig, err := s.apiUnit.NetworkConfig("db") // relation name, bound to "internal" 328 c.Assert(err, jc.ErrorIsNil) 329 c.Assert(netConfig, jc.DeepEquals, []params.NetworkConfig{ 330 {Address: "10.0.0.1"}, 331 {Address: "10.0.0.2"}, 332 }) 333 334 netConfig, err = s.apiUnit.NetworkConfig("admin-api") // extra-binding name, bound to "public" 335 c.Assert(err, jc.ErrorIsNil) 336 c.Assert(netConfig, jc.DeepEquals, []params.NetworkConfig{ 337 {Address: "8.8.8.8"}, 338 {Address: "fc00::1"}, 339 }) 340 341 netConfig, err = s.apiUnit.NetworkConfig("unknown") 342 c.Assert(err, gc.ErrorMatches, `binding name "unknown" not defined by the unit's charm`) 343 c.Assert(netConfig, gc.IsNil) 344 345 netConfig, err = s.apiUnit.NetworkConfig("") 346 c.Assert(err, gc.ErrorMatches, "binding name cannot be empty") 347 c.Assert(netConfig, gc.IsNil) 348 } 349 350 func (s *unitSuite) TestAvailabilityZone(c *gc.C) { 351 uniter.PatchUnitResponse(s, s.apiUnit, "AvailabilityZone", 352 func(result interface{}) error { 353 if results, ok := result.(*params.StringResults); ok { 354 results.Results = []params.StringResult{{ 355 Result: "a-zone", 356 }} 357 } 358 return nil 359 }, 360 ) 361 362 zone, err := s.apiUnit.AvailabilityZone() 363 c.Assert(err, jc.ErrorIsNil) 364 365 c.Check(zone, gc.Equals, "a-zone") 366 } 367 368 func (s *unitSuite) TestOpenClosePortRanges(c *gc.C) { 369 ports, err := s.wordpressUnit.OpenedPorts() 370 c.Assert(err, jc.ErrorIsNil) 371 c.Assert(ports, gc.HasLen, 0) 372 373 err = s.apiUnit.OpenPorts("tcp", 1234, 1400) 374 c.Assert(err, jc.ErrorIsNil) 375 err = s.apiUnit.OpenPorts("udp", 4321, 5000) 376 c.Assert(err, jc.ErrorIsNil) 377 378 ports, err = s.wordpressUnit.OpenedPorts() 379 c.Assert(err, jc.ErrorIsNil) 380 // OpenedPorts returns a sorted slice. 381 c.Assert(ports, gc.DeepEquals, []network.PortRange{ 382 {Protocol: "tcp", FromPort: 1234, ToPort: 1400}, 383 {Protocol: "udp", FromPort: 4321, ToPort: 5000}, 384 }) 385 386 err = s.apiUnit.ClosePorts("udp", 4321, 5000) 387 c.Assert(err, jc.ErrorIsNil) 388 389 ports, err = s.wordpressUnit.OpenedPorts() 390 c.Assert(err, jc.ErrorIsNil) 391 // OpenedPorts returns a sorted slice. 392 c.Assert(ports, gc.DeepEquals, []network.PortRange{ 393 {Protocol: "tcp", FromPort: 1234, ToPort: 1400}, 394 }) 395 396 err = s.apiUnit.ClosePorts("tcp", 1234, 1400) 397 c.Assert(err, jc.ErrorIsNil) 398 399 ports, err = s.wordpressUnit.OpenedPorts() 400 c.Assert(err, jc.ErrorIsNil) 401 c.Assert(ports, gc.HasLen, 0) 402 } 403 404 func (s *unitSuite) TestGetSetCharmURL(c *gc.C) { 405 // No charm URL set yet. 406 curl, ok := s.wordpressUnit.CharmURL() 407 c.Assert(curl, gc.IsNil) 408 c.Assert(ok, jc.IsFalse) 409 410 // Now check the same through the API. 411 _, err := s.apiUnit.CharmURL() 412 c.Assert(err, gc.Equals, uniter.ErrNoCharmURLSet) 413 414 err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL()) 415 c.Assert(err, jc.ErrorIsNil) 416 417 curl, err = s.apiUnit.CharmURL() 418 c.Assert(err, jc.ErrorIsNil) 419 c.Assert(curl, gc.NotNil) 420 c.Assert(curl.String(), gc.Equals, s.wordpressCharm.String()) 421 } 422 423 func (s *unitSuite) TestConfigSettings(c *gc.C) { 424 // Make sure ConfigSettings returns an error when 425 // no charm URL is set, as its state counterpart does. 426 settings, err := s.apiUnit.ConfigSettings() 427 c.Assert(err, gc.ErrorMatches, "unit charm not set") 428 429 // Now set the charm and try again. 430 err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL()) 431 c.Assert(err, jc.ErrorIsNil) 432 433 settings, err = s.apiUnit.ConfigSettings() 434 c.Assert(err, jc.ErrorIsNil) 435 c.Assert(settings, gc.DeepEquals, charm.Settings{ 436 "blog-title": "My Title", 437 }) 438 439 // Update the config and check we get the changes on the next call. 440 err = s.wordpressService.UpdateConfigSettings(charm.Settings{ 441 "blog-title": "superhero paparazzi", 442 }) 443 c.Assert(err, jc.ErrorIsNil) 444 445 settings, err = s.apiUnit.ConfigSettings() 446 c.Assert(err, jc.ErrorIsNil) 447 c.Assert(settings, gc.DeepEquals, charm.Settings{ 448 "blog-title": "superhero paparazzi", 449 }) 450 } 451 452 func (s *unitSuite) TestWatchConfigSettings(c *gc.C) { 453 // Make sure WatchConfigSettings returns an error when 454 // no charm URL is set, as its state counterpart does. 455 w, err := s.apiUnit.WatchConfigSettings() 456 c.Assert(err, gc.ErrorMatches, "unit charm not set") 457 458 // Now set the charm and try again. 459 err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL()) 460 c.Assert(err, jc.ErrorIsNil) 461 462 w, err = s.apiUnit.WatchConfigSettings() 463 wc := watchertest.NewNotifyWatcherC(c, w, s.BackingState.StartSync) 464 defer wc.AssertStops() 465 466 // Initial event. 467 wc.AssertOneChange() 468 469 // Update config a couple of times, check a single event. 470 err = s.wordpressService.UpdateConfigSettings(charm.Settings{ 471 "blog-title": "superhero paparazzi", 472 }) 473 c.Assert(err, jc.ErrorIsNil) 474 err = s.wordpressService.UpdateConfigSettings(charm.Settings{ 475 "blog-title": "sauceror central", 476 }) 477 c.Assert(err, jc.ErrorIsNil) 478 wc.AssertOneChange() 479 480 // Non-change is not reported. 481 err = s.wordpressService.UpdateConfigSettings(charm.Settings{ 482 "blog-title": "sauceror central", 483 }) 484 c.Assert(err, jc.ErrorIsNil) 485 wc.AssertNoChange() 486 } 487 488 func (s *unitSuite) TestWatchActionNotifications(c *gc.C) { 489 w, err := s.apiUnit.WatchActionNotifications() 490 c.Assert(err, jc.ErrorIsNil) 491 wc := watchertest.NewStringsWatcherC(c, w, s.BackingState.StartSync) 492 defer wc.AssertStops() 493 494 // Initial event. 495 wc.AssertChange() 496 497 // Add a couple of actions and make sure the changes are detected. 498 action, err := s.wordpressUnit.AddAction("fakeaction", map[string]interface{}{ 499 "outfile": "foo.txt", 500 }) 501 c.Assert(err, jc.ErrorIsNil) 502 wc.AssertChange(action.Id()) 503 504 action, err = s.wordpressUnit.AddAction("fakeaction", map[string]interface{}{ 505 "outfile": "foo.bz2", 506 "compression": map[string]interface{}{ 507 "kind": "bzip", 508 "quality": float64(5.0), 509 }, 510 }) 511 c.Assert(err, jc.ErrorIsNil) 512 wc.AssertChange(action.Id()) 513 } 514 515 func (s *unitSuite) TestWatchActionNotificationsError(c *gc.C) { 516 uniter.PatchUnitResponse(s, s.apiUnit, "WatchActionNotifications", 517 func(result interface{}) error { 518 return fmt.Errorf("Test error") 519 }, 520 ) 521 522 _, err := s.apiUnit.WatchActionNotifications() 523 c.Assert(err.Error(), gc.Equals, "Test error") 524 } 525 526 func (s *unitSuite) TestWatchActionNotificationsErrorResults(c *gc.C) { 527 uniter.PatchUnitResponse(s, s.apiUnit, "WatchActionNotifications", 528 func(results interface{}) error { 529 if results, ok := results.(*params.StringsWatchResults); ok { 530 results.Results = make([]params.StringsWatchResult, 1) 531 results.Results[0] = params.StringsWatchResult{ 532 Error: ¶ms.Error{ 533 Message: "An error in the watch result.", 534 Code: params.CodeNotAssigned, 535 }, 536 } 537 } 538 return nil 539 }, 540 ) 541 542 _, err := s.apiUnit.WatchActionNotifications() 543 c.Assert(err.Error(), gc.Equals, "An error in the watch result.") 544 } 545 546 func (s *unitSuite) TestWatchActionNotificationsNoResults(c *gc.C) { 547 uniter.PatchUnitResponse(s, s.apiUnit, "WatchActionNotifications", 548 func(results interface{}) error { 549 return nil 550 }, 551 ) 552 553 _, err := s.apiUnit.WatchActionNotifications() 554 c.Assert(err.Error(), gc.Equals, "expected 1 result, got 0") 555 } 556 557 func (s *unitSuite) TestWatchActionNotificationsMoreResults(c *gc.C) { 558 uniter.PatchUnitResponse(s, s.apiUnit, "WatchActionNotifications", 559 func(results interface{}) error { 560 if results, ok := results.(*params.StringsWatchResults); ok { 561 results.Results = make([]params.StringsWatchResult, 2) 562 } 563 return nil 564 }, 565 ) 566 567 _, err := s.apiUnit.WatchActionNotifications() 568 c.Assert(err.Error(), gc.Equals, "expected 1 result, got 2") 569 } 570 571 func (s *unitSuite) TestServiceNameAndTag(c *gc.C) { 572 c.Assert(s.apiUnit.ApplicationName(), gc.Equals, s.wordpressService.Name()) 573 c.Assert(s.apiUnit.ApplicationTag(), gc.Equals, s.wordpressService.Tag()) 574 } 575 576 func (s *unitSuite) TestJoinedRelations(c *gc.C) { 577 joinedRelations, err := s.apiUnit.JoinedRelations() 578 c.Assert(err, jc.ErrorIsNil) 579 c.Assert(joinedRelations, gc.HasLen, 0) 580 581 rel1, _, _ := s.addRelatedService(c, "wordpress", "monitoring", s.wordpressUnit) 582 joinedRelations, err = s.apiUnit.JoinedRelations() 583 c.Assert(err, jc.ErrorIsNil) 584 c.Assert(joinedRelations, gc.DeepEquals, []names.RelationTag{ 585 rel1.Tag().(names.RelationTag), 586 }) 587 588 rel2, _, _ := s.addRelatedService(c, "wordpress", "logging", s.wordpressUnit) 589 joinedRelations, err = s.apiUnit.JoinedRelations() 590 c.Assert(err, jc.ErrorIsNil) 591 c.Assert(joinedRelations, jc.SameContents, []names.RelationTag{ 592 rel1.Tag().(names.RelationTag), 593 rel2.Tag().(names.RelationTag), 594 }) 595 } 596 597 func (s *unitSuite) TestWatchAddresses(c *gc.C) { 598 w, err := s.apiUnit.WatchAddresses() 599 c.Assert(err, jc.ErrorIsNil) 600 wc := watchertest.NewNotifyWatcherC(c, w, s.BackingState.StartSync) 601 defer wc.AssertStops() 602 603 // Initial event. 604 wc.AssertOneChange() 605 606 // Update config a couple of times, check a single event. 607 err = s.wordpressMachine.SetProviderAddresses(network.NewAddress("0.1.2.3")) 608 c.Assert(err, jc.ErrorIsNil) 609 err = s.wordpressMachine.SetProviderAddresses(network.NewAddress("0.1.2.4")) 610 c.Assert(err, jc.ErrorIsNil) 611 wc.AssertOneChange() 612 613 // Non-change is not reported. 614 err = s.wordpressMachine.SetProviderAddresses(network.NewAddress("0.1.2.4")) 615 c.Assert(err, jc.ErrorIsNil) 616 wc.AssertNoChange() 617 618 // Change is reported for machine addresses. 619 err = s.wordpressMachine.SetMachineAddresses(network.NewAddress("0.1.2.5")) 620 c.Assert(err, jc.ErrorIsNil) 621 wc.AssertOneChange() 622 623 // Set machine addresses to empty is reported. 624 err = s.wordpressMachine.SetMachineAddresses() 625 c.Assert(err, jc.ErrorIsNil) 626 wc.AssertOneChange() 627 } 628 629 func (s *unitSuite) TestWatchAddressesErrors(c *gc.C) { 630 err := s.wordpressUnit.UnassignFromMachine() 631 c.Assert(err, jc.ErrorIsNil) 632 _, err = s.apiUnit.WatchAddresses() 633 c.Assert(err, jc.Satisfies, params.IsCodeNotAssigned) 634 } 635 636 func (s *unitSuite) TestAddMetrics(c *gc.C) { 637 uniter.PatchUnitResponse(s, s.apiUnit, "AddMetrics", 638 func(results interface{}) error { 639 result := results.(*params.ErrorResults) 640 result.Results = make([]params.ErrorResult, 1) 641 return nil 642 }, 643 ) 644 metrics := []params.Metric{{"A", "23", time.Now()}, {"B", "27.0", time.Now()}} 645 err := s.apiUnit.AddMetrics(metrics) 646 c.Assert(err, jc.ErrorIsNil) 647 } 648 649 func (s *unitSuite) TestAddMetricsError(c *gc.C) { 650 uniter.PatchUnitResponse(s, s.apiUnit, "AddMetrics", 651 func(results interface{}) error { 652 result := results.(*params.ErrorResults) 653 result.Results = make([]params.ErrorResult, 1) 654 return fmt.Errorf("test error") 655 }, 656 ) 657 metrics := []params.Metric{{"A", "23", time.Now()}, {"B", "27.0", time.Now()}} 658 err := s.apiUnit.AddMetrics(metrics) 659 c.Assert(err, gc.ErrorMatches, "unable to add metric: test error") 660 } 661 662 func (s *unitSuite) TestAddMetricsResultError(c *gc.C) { 663 uniter.PatchUnitResponse(s, s.apiUnit, "AddMetrics", 664 func(results interface{}) error { 665 result := results.(*params.ErrorResults) 666 result.Results = make([]params.ErrorResult, 1) 667 result.Results[0].Error = ¶ms.Error{ 668 Message: "error adding metrics", 669 Code: params.CodeNotAssigned, 670 } 671 return nil 672 }, 673 ) 674 metrics := []params.Metric{{"A", "23", time.Now()}, {"B", "27.0", time.Now()}} 675 err := s.apiUnit.AddMetrics(metrics) 676 c.Assert(err, gc.ErrorMatches, "error adding metrics") 677 } 678 679 func (s *unitSuite) TestMeterStatus(c *gc.C) { 680 uniter.PatchUnitResponse(s, s.apiUnit, "GetMeterStatus", 681 func(results interface{}) error { 682 result := results.(*params.MeterStatusResults) 683 result.Results = make([]params.MeterStatusResult, 1) 684 result.Results[0].Code = "GREEN" 685 result.Results[0].Info = "All ok." 686 return nil 687 }, 688 ) 689 statusCode, statusInfo, err := s.apiUnit.MeterStatus() 690 c.Assert(err, jc.ErrorIsNil) 691 c.Assert(statusCode, gc.Equals, "GREEN") 692 c.Assert(statusInfo, gc.Equals, "All ok.") 693 } 694 695 func (s *unitSuite) TestMeterStatusError(c *gc.C) { 696 uniter.PatchUnitResponse(s, s.apiUnit, "GetMeterStatus", 697 func(results interface{}) error { 698 result := results.(*params.MeterStatusResults) 699 result.Results = make([]params.MeterStatusResult, 1) 700 return fmt.Errorf("boo") 701 }, 702 ) 703 statusCode, statusInfo, err := s.apiUnit.MeterStatus() 704 c.Assert(err, gc.ErrorMatches, "boo") 705 c.Assert(statusCode, gc.Equals, "") 706 c.Assert(statusInfo, gc.Equals, "") 707 } 708 709 func (s *unitSuite) TestMeterStatusResultError(c *gc.C) { 710 uniter.PatchUnitResponse(s, s.apiUnit, "GetMeterStatus", 711 func(results interface{}) error { 712 result := results.(*params.MeterStatusResults) 713 result.Results = make([]params.MeterStatusResult, 1) 714 result.Results[0].Error = ¶ms.Error{ 715 Message: "error getting meter status", 716 Code: params.CodeNotAssigned, 717 } 718 return nil 719 }, 720 ) 721 statusCode, statusInfo, err := s.apiUnit.MeterStatus() 722 c.Assert(err, gc.ErrorMatches, "error getting meter status") 723 c.Assert(statusCode, gc.Equals, "") 724 c.Assert(statusInfo, gc.Equals, "") 725 } 726 727 func (s *unitSuite) TestWatchMeterStatus(c *gc.C) { 728 w, err := s.apiUnit.WatchMeterStatus() 729 wc := watchertest.NewNotifyWatcherC(c, w, s.BackingState.StartSync) 730 defer wc.AssertStops() 731 732 // Initial event. 733 wc.AssertOneChange() 734 735 err = s.wordpressUnit.SetMeterStatus("GREEN", "ok") 736 c.Assert(err, jc.ErrorIsNil) 737 err = s.wordpressUnit.SetMeterStatus("AMBER", "ok") 738 c.Assert(err, jc.ErrorIsNil) 739 wc.AssertOneChange() 740 741 // Non-change is not reported. 742 err = s.wordpressUnit.SetMeterStatus("AMBER", "ok") 743 c.Assert(err, jc.ErrorIsNil) 744 wc.AssertNoChange() 745 746 mm, err := s.State.MetricsManager() 747 c.Assert(err, jc.ErrorIsNil) 748 err = mm.SetLastSuccessfulSend(time.Now()) 749 c.Assert(err, jc.ErrorIsNil) 750 for i := 0; i < 3; i++ { 751 err := mm.IncrementConsecutiveErrors() 752 c.Assert(err, jc.ErrorIsNil) 753 } 754 status := mm.MeterStatus() 755 c.Assert(status.Code, gc.Equals, state.MeterAmber) // Confirm meter status has changed 756 wc.AssertOneChange() 757 } 758 759 func (s *unitSuite) patchNewState( 760 c *gc.C, 761 patchFunc func(_ base.APICaller, _ names.UnitTag) *uniter.State, 762 ) { 763 s.uniterSuite.patchNewState(c, patchFunc) 764 var err error 765 s.apiUnit, err = s.uniter.Unit(s.wordpressUnit.Tag().(names.UnitTag)) 766 c.Assert(err, jc.ErrorIsNil) 767 } 768 769 type unitMetricBatchesSuite struct { 770 testing.JujuConnSuite 771 772 st api.Connection 773 uniter *uniter.State 774 apiUnit *uniter.Unit 775 charm *state.Charm 776 } 777 778 var _ = gc.Suite(&unitMetricBatchesSuite{}) 779 780 func (s *unitMetricBatchesSuite) SetUpTest(c *gc.C) { 781 s.JujuConnSuite.SetUpTest(c) 782 783 s.charm = s.Factory.MakeCharm(c, &jujufactory.CharmParams{ 784 Name: "metered", 785 URL: "cs:quantal/metered", 786 }) 787 service := s.Factory.MakeApplication(c, &jujufactory.ApplicationParams{ 788 Charm: s.charm, 789 }) 790 unit := s.Factory.MakeUnit(c, &jujufactory.UnitParams{ 791 Application: service, 792 SetCharmURL: true, 793 }) 794 795 password, err := utils.RandomPassword() 796 c.Assert(err, jc.ErrorIsNil) 797 err = unit.SetPassword(password) 798 c.Assert(err, jc.ErrorIsNil) 799 s.st = s.OpenAPIAs(c, unit.Tag(), password) 800 801 // Create the uniter API facade. 802 s.uniter, err = s.st.Uniter() 803 c.Assert(err, jc.ErrorIsNil) 804 c.Assert(s.uniter, gc.NotNil) 805 806 s.apiUnit, err = s.uniter.Unit(unit.Tag().(names.UnitTag)) 807 c.Assert(err, jc.ErrorIsNil) 808 } 809 810 func (s *unitMetricBatchesSuite) TestSendMetricBatchPatch(c *gc.C) { 811 metrics := []params.Metric{{"pings", "5", time.Now().UTC()}} 812 uuid := utils.MustNewUUID().String() 813 batch := params.MetricBatch{ 814 UUID: uuid, 815 CharmURL: s.charm.URL().String(), 816 Created: time.Now(), 817 Metrics: metrics, 818 } 819 820 var called bool 821 uniter.PatchUnitResponse(s, s.apiUnit, "AddMetricBatches", 822 func(response interface{}) error { 823 called = true 824 result := response.(*params.ErrorResults) 825 result.Results = make([]params.ErrorResult, 1) 826 return nil 827 }) 828 829 results, err := s.apiUnit.AddMetricBatches([]params.MetricBatch{batch}) 830 c.Assert(err, jc.ErrorIsNil) 831 c.Assert(results, gc.HasLen, 1) 832 c.Assert(results[batch.UUID], gc.IsNil) 833 c.Assert(called, jc.IsTrue) 834 } 835 836 func (s *unitMetricBatchesSuite) TestSendMetricBatchFail(c *gc.C) { 837 var called bool 838 uniter.PatchUnitResponse(s, s.apiUnit, "AddMetricBatches", 839 func(response interface{}) error { 840 called = true 841 result := response.(*params.ErrorResults) 842 result.Results = make([]params.ErrorResult, 1) 843 result.Results[0].Error = common.ServerError(common.ErrPerm) 844 return nil 845 }) 846 metrics := []params.Metric{{"pings", "5", time.Now().UTC()}} 847 uuid := utils.MustNewUUID().String() 848 batch := params.MetricBatch{ 849 UUID: uuid, 850 CharmURL: s.charm.URL().String(), 851 Created: time.Now(), 852 Metrics: metrics, 853 } 854 855 results, err := s.apiUnit.AddMetricBatches([]params.MetricBatch{batch}) 856 c.Assert(err, jc.ErrorIsNil) 857 c.Assert(results, gc.HasLen, 1) 858 c.Assert(results[batch.UUID], gc.ErrorMatches, "permission denied") 859 c.Assert(called, jc.IsTrue) 860 } 861 862 func (s *unitMetricBatchesSuite) TestSendMetricBatch(c *gc.C) { 863 uuid := utils.MustNewUUID().String() 864 now := time.Now().Round(time.Second).UTC() 865 metrics := []params.Metric{{"pings", "5", now}} 866 batch := params.MetricBatch{ 867 UUID: uuid, 868 CharmURL: s.charm.URL().String(), 869 Created: now, 870 Metrics: metrics, 871 } 872 873 results, err := s.apiUnit.AddMetricBatches([]params.MetricBatch{batch}) 874 c.Assert(err, jc.ErrorIsNil) 875 c.Assert(results, gc.HasLen, 1) 876 c.Assert(results[batch.UUID], gc.IsNil) 877 878 batches, err := s.State.AllMetricBatches() 879 c.Assert(err, gc.IsNil) 880 c.Assert(batches, gc.HasLen, 1) 881 c.Assert(batches[0].UUID(), gc.Equals, uuid) 882 c.Assert(batches[0].Sent(), jc.IsFalse) 883 c.Assert(batches[0].CharmURL(), gc.Equals, s.charm.URL().String()) 884 c.Assert(batches[0].Metrics(), gc.HasLen, 1) 885 c.Assert(batches[0].Metrics()[0].Key, gc.Equals, "pings") 886 c.Assert(batches[0].Metrics()[0].Key, gc.Equals, "pings") 887 c.Assert(batches[0].Metrics()[0].Value, gc.Equals, "5") 888 }