1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
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"
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"
30
type unitSuite struct {
36
var _ = gc.Suite(&unitSuite{})
38
func (s *unitSuite) SetUpTest(c *gc.C) {
39
s.uniterSuite.SetUpTest(c)
42
s.apiUnit, err = s.uniter.Unit(s.wordpressUnit.Tag().(names.UnitTag))
43
c.Assert(err, jc.ErrorIsNil)
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)
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)
60
c.Assert(s.apiUnit.Tag(), gc.Equals, s.wordpressUnit.Tag().(names.UnitTag))
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)
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)
76
err = s.apiUnit.SetAgentStatus(status.StatusIdle, "blah", nil)
77
c.Assert(err, jc.ErrorIsNil)
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)
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)
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)
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)
107
err = s.apiUnit.SetUnitStatus(status.StatusActive, "blah", nil)
108
c.Assert(err, jc.ErrorIsNil)
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)
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)
125
func (s *unitSuite) TestUnitStatus(c *gc.C) {
127
sInfo := status.StatusInfo{
128
Status: status.StatusMaintenance,
132
err := s.wordpressUnit.SetStatus(sInfo)
133
c.Assert(err, jc.ErrorIsNil)
135
result, err := s.apiUnit.UnitStatus()
136
c.Assert(err, jc.ErrorIsNil)
137
c.Assert(result.Since, gc.NotNil)
139
c.Assert(result, gc.DeepEquals, params.StatusResult{
140
Status: status.StatusMaintenance.String(),
142
Data: map[string]interface{}{},
146
func (s *unitSuite) TestEnsureDead(c *gc.C) {
147
c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
149
err := s.apiUnit.EnsureDead()
150
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)
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)
162
err = s.wordpressUnit.Remove()
163
c.Assert(err, jc.ErrorIsNil)
164
err = s.wordpressUnit.Refresh()
165
c.Assert(err, jc.Satisfies, errors.IsNotFound)
167
err = s.apiUnit.EnsureDead()
168
c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`)
169
c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
172
func (s *unitSuite) TestDestroy(c *gc.C) {
173
c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
175
err := s.apiUnit.Destroy()
176
c.Assert(err, jc.ErrorIsNil)
178
err = s.wordpressUnit.Refresh()
179
c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`)
182
func (s *unitSuite) TestDestroyAllSubordinates(c *gc.C) {
183
c.Assert(s.wordpressUnit.Life(), gc.Equals, state.Alive)
185
// Call without subordinates - no change.
186
err := s.apiUnit.DestroyAllSubordinates()
187
c.Assert(err, jc.ErrorIsNil)
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)
195
err = s.apiUnit.DestroyAllSubordinates()
196
c.Assert(err, jc.ErrorIsNil)
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)
207
func (s *unitSuite) TestRefresh(c *gc.C) {
208
c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
210
err := s.apiUnit.EnsureDead()
211
c.Assert(err, jc.ErrorIsNil)
212
c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
214
err = s.apiUnit.Refresh()
215
c.Assert(err, jc.ErrorIsNil)
216
c.Assert(s.apiUnit.Life(), gc.Equals, params.Dead)
219
func (s *unitSuite) TestWatch(c *gc.C) {
220
c.Assert(s.apiUnit.Life(), gc.Equals, params.Alive)
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()
230
// Change something other than the lifecycle and make sure it's
232
err = s.apiUnit.SetAgentStatus(status.StatusIdle, "not really", nil)
233
c.Assert(err, jc.ErrorIsNil)
236
// Make the unit dead and check it's detected.
237
err = s.apiUnit.EnsureDead()
238
c.Assert(err, jc.ErrorIsNil)
242
func (s *unitSuite) TestResolve(c *gc.C) {
243
err := s.wordpressUnit.SetResolved(state.ResolvedRetryHooks)
244
c.Assert(err, jc.ErrorIsNil)
246
mode, err := s.apiUnit.Resolved()
247
c.Assert(err, jc.ErrorIsNil)
248
c.Assert(mode, gc.Equals, params.ResolvedRetryHooks)
250
err = s.apiUnit.ClearResolved()
251
c.Assert(err, jc.ErrorIsNil)
253
mode, err = s.apiUnit.Resolved()
254
c.Assert(err, jc.ErrorIsNil)
255
c.Assert(mode, gc.Equals, params.ResolvedNone)
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())
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)
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)
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)
279
found, err = s.apiUnit.HasSubordinates()
280
c.Assert(err, jc.ErrorIsNil)
281
c.Assert(found, jc.IsTrue)
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`)
288
err = s.wordpressMachine.SetProviderAddresses(
289
network.NewScopedAddress("1.2.3.4", network.ScopePublic),
291
c.Assert(err, jc.ErrorIsNil)
293
address, err = s.apiUnit.PublicAddress()
294
c.Assert(err, jc.ErrorIsNil)
295
c.Assert(address, gc.Equals, "1.2.3.4")
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`)
302
err = s.wordpressMachine.SetProviderAddresses(
303
network.NewScopedAddress("1.2.3.4", network.ScopeCloudLocal),
305
c.Assert(err, jc.ErrorIsNil)
307
address, err = s.apiUnit.PrivateAddress()
308
c.Assert(err, jc.ErrorIsNil)
309
c.Assert(address, gc.Equals, "1.2.3.4")
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")
315
// Set some provider addresses bound to both "public" and "internal"
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"),
324
err := s.wordpressMachine.SetProviderAddresses(addresses...)
325
c.Assert(err, jc.ErrorIsNil)
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"},
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"},
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)
345
netConfig, err = s.apiUnit.NetworkConfig("")
346
c.Assert(err, gc.ErrorMatches, "binding name cannot be empty")
347
c.Assert(netConfig, gc.IsNil)
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{{
362
zone, err := s.apiUnit.AvailabilityZone()
363
c.Assert(err, jc.ErrorIsNil)
365
c.Check(zone, gc.Equals, "a-zone")
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)
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)
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},
386
err = s.apiUnit.ClosePorts("udp", 4321, 5000)
387
c.Assert(err, jc.ErrorIsNil)
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},
396
err = s.apiUnit.ClosePorts("tcp", 1234, 1400)
397
c.Assert(err, jc.ErrorIsNil)
399
ports, err = s.wordpressUnit.OpenedPorts()
400
c.Assert(err, jc.ErrorIsNil)
401
c.Assert(ports, gc.HasLen, 0)
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)
410
// Now check the same through the API.
411
_, err := s.apiUnit.CharmURL()
412
c.Assert(err, gc.Equals, uniter.ErrNoCharmURLSet)
414
err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
415
c.Assert(err, jc.ErrorIsNil)
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())
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")
429
// Now set the charm and try again.
430
err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
431
c.Assert(err, jc.ErrorIsNil)
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",
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",
443
c.Assert(err, jc.ErrorIsNil)
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",
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")
458
// Now set the charm and try again.
459
err = s.apiUnit.SetCharmURL(s.wordpressCharm.URL())
460
c.Assert(err, jc.ErrorIsNil)
462
w, err = s.apiUnit.WatchConfigSettings()
463
wc := watchertest.NewNotifyWatcherC(c, w, s.BackingState.StartSync)
464
defer wc.AssertStops()
469
// Update config a couple of times, check a single event.
470
err = s.wordpressService.UpdateConfigSettings(charm.Settings{
471
"blog-title": "superhero paparazzi",
473
c.Assert(err, jc.ErrorIsNil)
474
err = s.wordpressService.UpdateConfigSettings(charm.Settings{
475
"blog-title": "sauceror central",
477
c.Assert(err, jc.ErrorIsNil)
480
// Non-change is not reported.
481
err = s.wordpressService.UpdateConfigSettings(charm.Settings{
482
"blog-title": "sauceror central",
484
c.Assert(err, jc.ErrorIsNil)
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()
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",
501
c.Assert(err, jc.ErrorIsNil)
502
wc.AssertChange(action.Id())
504
action, err = s.wordpressUnit.AddAction("fakeaction", map[string]interface{}{
505
"outfile": "foo.bz2",
506
"compression": map[string]interface{}{
508
"quality": float64(5.0),
511
c.Assert(err, jc.ErrorIsNil)
512
wc.AssertChange(action.Id())
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")
522
_, err := s.apiUnit.WatchActionNotifications()
523
c.Assert(err.Error(), gc.Equals, "Test error")
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,
542
_, err := s.apiUnit.WatchActionNotifications()
543
c.Assert(err.Error(), gc.Equals, "An error in the watch result.")
546
func (s *unitSuite) TestWatchActionNotificationsNoResults(c *gc.C) {
547
uniter.PatchUnitResponse(s, s.apiUnit, "WatchActionNotifications",
548
func(results interface{}) error {
553
_, err := s.apiUnit.WatchActionNotifications()
554
c.Assert(err.Error(), gc.Equals, "expected 1 result, got 0")
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)
567
_, err := s.apiUnit.WatchActionNotifications()
568
c.Assert(err.Error(), gc.Equals, "expected 1 result, got 2")
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())
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)
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),
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),
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()
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)
613
// Non-change is not reported.
614
err = s.wordpressMachine.SetProviderAddresses(network.NewAddress("0.1.2.4"))
615
c.Assert(err, jc.ErrorIsNil)
618
// Change is reported for machine addresses.
619
err = s.wordpressMachine.SetMachineAddresses(network.NewAddress("0.1.2.5"))
620
c.Assert(err, jc.ErrorIsNil)
623
// Set machine addresses to empty is reported.
624
err = s.wordpressMachine.SetMachineAddresses()
625
c.Assert(err, jc.ErrorIsNil)
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)
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)
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)
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")
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")
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,
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")
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."
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.")
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")
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, "")
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,
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, "")
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()
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)
741
// Non-change is not reported.
742
err = s.wordpressUnit.SetMeterStatus("AMBER", "ok")
743
c.Assert(err, jc.ErrorIsNil)
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)
754
status := mm.MeterStatus()
755
c.Assert(status.Code, gc.Equals, state.MeterAmber) // Confirm meter status has changed
759
func (s *unitSuite) patchNewState(
761
patchFunc func(_ base.APICaller, _ names.UnitTag) *uniter.State,
763
s.uniterSuite.patchNewState(c, patchFunc)
765
s.apiUnit, err = s.uniter.Unit(s.wordpressUnit.Tag().(names.UnitTag))
766
c.Assert(err, jc.ErrorIsNil)
769
type unitMetricBatchesSuite struct {
770
testing.JujuConnSuite
778
var _ = gc.Suite(&unitMetricBatchesSuite{})
780
func (s *unitMetricBatchesSuite) SetUpTest(c *gc.C) {
781
s.JujuConnSuite.SetUpTest(c)
783
s.charm = s.Factory.MakeCharm(c, &jujufactory.CharmParams{
785
URL: "cs:quantal/metered",
787
service := s.Factory.MakeApplication(c, &jujufactory.ApplicationParams{
790
unit := s.Factory.MakeUnit(c, &jujufactory.UnitParams{
791
Application: service,
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)
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)
806
s.apiUnit, err = s.uniter.Unit(unit.Tag().(names.UnitTag))
807
c.Assert(err, jc.ErrorIsNil)
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{
815
CharmURL: s.charm.URL().String(),
821
uniter.PatchUnitResponse(s, s.apiUnit, "AddMetricBatches",
822
func(response interface{}) error {
824
result := response.(*params.ErrorResults)
825
result.Results = make([]params.ErrorResult, 1)
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)
836
func (s *unitMetricBatchesSuite) TestSendMetricBatchFail(c *gc.C) {
838
uniter.PatchUnitResponse(s, s.apiUnit, "AddMetricBatches",
839
func(response interface{}) error {
841
result := response.(*params.ErrorResults)
842
result.Results = make([]params.ErrorResult, 1)
843
result.Results[0].Error = common.ServerError(common.ErrPerm)
846
metrics := []params.Metric{{"pings", "5", time.Now().UTC()}}
847
uuid := utils.MustNewUUID().String()
848
batch := params.MetricBatch{
850
CharmURL: s.charm.URL().String(),
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)
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{
868
CharmURL: s.charm.URL().String(),
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)
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")