~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/api/uniter/unit_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.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
        now := time.Now()
 
127
        sInfo := status.StatusInfo{
 
128
                Status:  status.StatusMaintenance,
 
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.StatusMaintenance.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.StatusIdle, "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: &params.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 = &params.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 = &params.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
}