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