~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/core/description/machine_test.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package description
 
5
 
 
6
import (
 
7
        "github.com/juju/names"
 
8
        jc "github.com/juju/testing/checkers"
 
9
        "github.com/juju/version"
 
10
        gc "gopkg.in/check.v1"
 
11
        "gopkg.in/yaml.v2"
 
12
)
 
13
 
 
14
type MachineSerializationSuite struct {
 
15
        SliceSerializationSuite
 
16
        PortRangeCheck
 
17
        StatusHistoryMixinSuite
 
18
}
 
19
 
 
20
var _ = gc.Suite(&MachineSerializationSuite{})
 
21
 
 
22
func (s *MachineSerializationSuite) SetUpTest(c *gc.C) {
 
23
        s.SliceSerializationSuite.SetUpTest(c)
 
24
        s.importName = "machines"
 
25
        s.sliceName = "machines"
 
26
        s.importFunc = func(m map[string]interface{}) (interface{}, error) {
 
27
                return importMachines(m)
 
28
        }
 
29
        s.testFields = func(m map[string]interface{}) {
 
30
                m["machines"] = []interface{}{}
 
31
        }
 
32
        s.StatusHistoryMixinSuite.creator = func() HasStatusHistory {
 
33
                return minimalMachine("1")
 
34
        }
 
35
        s.StatusHistoryMixinSuite.serializer = func(c *gc.C, initial interface{}) HasStatusHistory {
 
36
                return s.exportImport(c, initial.(*machine))
 
37
        }
 
38
}
 
39
 
 
40
func minimalMachineMap(id string, containers ...interface{}) map[interface{}]interface{} {
 
41
        return map[interface{}]interface{}{
 
42
                "id":             id,
 
43
                "nonce":          "a-nonce",
 
44
                "password-hash":  "some-hash",
 
45
                "instance":       minimalCloudInstanceMap(),
 
46
                "series":         "zesty",
 
47
                "tools":          minimalAgentToolsMap(),
 
48
                "jobs":           []interface{}{"host-units"},
 
49
                "containers":     containers,
 
50
                "status":         minimalStatusMap(),
 
51
                "status-history": emptyStatusHistoryMap(),
 
52
        }
 
53
}
 
54
 
 
55
func minimalMachine(id string, containers ...*machine) *machine {
 
56
        m := newMachine(MachineArgs{
 
57
                Id:           names.NewMachineTag(id),
 
58
                Nonce:        "a-nonce",
 
59
                PasswordHash: "some-hash",
 
60
                Series:       "zesty",
 
61
                Jobs:         []string{"host-units"},
 
62
        })
 
63
        m.Containers_ = containers
 
64
        m.SetInstance(minimalCloudInstanceArgs())
 
65
        m.SetTools(minimalAgentToolsArgs())
 
66
        m.SetStatus(minimalStatusArgs())
 
67
        return m
 
68
}
 
69
 
 
70
func addMinimalMachine(model Model, id string) {
 
71
        m := model.AddMachine(MachineArgs{
 
72
                Id:           names.NewMachineTag(id),
 
73
                Nonce:        "a-nonce",
 
74
                PasswordHash: "some-hash",
 
75
                Series:       "zesty",
 
76
                Jobs:         []string{"host-units"},
 
77
        })
 
78
        m.SetInstance(minimalCloudInstanceArgs())
 
79
        m.SetTools(minimalAgentToolsArgs())
 
80
        m.SetStatus(minimalStatusArgs())
 
81
}
 
82
 
 
83
func (s *MachineSerializationSuite) machineArgs(id string) MachineArgs {
 
84
        return MachineArgs{
 
85
                Id:            names.NewMachineTag(id),
 
86
                Nonce:         "a nonce",
 
87
                PasswordHash:  "some-hash",
 
88
                Placement:     "placement",
 
89
                Series:        "zesty",
 
90
                ContainerType: "magic",
 
91
                Jobs:          []string{"this", "that"},
 
92
        }
 
93
}
 
94
 
 
95
func (s *MachineSerializationSuite) TestNewMachine(c *gc.C) {
 
96
        m := newMachine(s.machineArgs("42"))
 
97
        c.Assert(m.Id(), gc.Equals, "42")
 
98
        c.Assert(m.Tag(), gc.Equals, names.NewMachineTag("42"))
 
99
        c.Assert(m.Nonce(), gc.Equals, "a nonce")
 
100
        c.Assert(m.PasswordHash(), gc.Equals, "some-hash")
 
101
        c.Assert(m.Placement(), gc.Equals, "placement")
 
102
        c.Assert(m.Series(), gc.Equals, "zesty")
 
103
        c.Assert(m.ContainerType(), gc.Equals, "magic")
 
104
        c.Assert(m.Jobs(), jc.DeepEquals, []string{"this", "that"})
 
105
        supportedContainers, ok := m.SupportedContainers()
 
106
        c.Assert(ok, jc.IsFalse)
 
107
        c.Assert(supportedContainers, gc.IsNil)
 
108
}
 
109
 
 
110
func (s *MachineSerializationSuite) TestMinimalMachineValid(c *gc.C) {
 
111
        m := minimalMachine("1")
 
112
        c.Assert(m.Validate(), jc.ErrorIsNil)
 
113
}
 
114
 
 
115
func (s *MachineSerializationSuite) TestNewMachineWithSupportedContainers(c *gc.C) {
 
116
        supported := []string{"lxd", "kvm"}
 
117
        args := s.machineArgs("id")
 
118
        args.SupportedContainers = &supported
 
119
        m := newMachine(args)
 
120
        supportedContainers, ok := m.SupportedContainers()
 
121
        c.Assert(ok, jc.IsTrue)
 
122
        c.Assert(supportedContainers, jc.DeepEquals, supported)
 
123
}
 
124
 
 
125
func (s *MachineSerializationSuite) TestNewMachineWithNoSupportedContainers(c *gc.C) {
 
126
        supported := []string{}
 
127
        args := s.machineArgs("id")
 
128
        args.SupportedContainers = &supported
 
129
        m := newMachine(args)
 
130
        supportedContainers, ok := m.SupportedContainers()
 
131
        c.Assert(ok, jc.IsTrue)
 
132
        c.Assert(supportedContainers, gc.HasLen, 0)
 
133
}
 
134
 
 
135
func (s *MachineSerializationSuite) TestNewMachineWithNoSupportedContainersNil(c *gc.C) {
 
136
        var supported []string
 
137
        args := s.machineArgs("id")
 
138
        args.SupportedContainers = &supported
 
139
        m := newMachine(args)
 
140
        supportedContainers, ok := m.SupportedContainers()
 
141
        c.Assert(ok, jc.IsTrue)
 
142
        c.Assert(supportedContainers, gc.HasLen, 0)
 
143
}
 
144
 
 
145
func (s *MachineSerializationSuite) TestMinimalMatches(c *gc.C) {
 
146
        bytes, err := yaml.Marshal(minimalMachine("0"))
 
147
        c.Assert(err, jc.ErrorIsNil)
 
148
 
 
149
        var source map[interface{}]interface{}
 
150
        err = yaml.Unmarshal(bytes, &source)
 
151
        c.Assert(err, jc.ErrorIsNil)
 
152
        c.Assert(source, jc.DeepEquals, minimalMachineMap("0"))
 
153
}
 
154
 
 
155
func (*MachineSerializationSuite) TestNestedParsing(c *gc.C) {
 
156
        machines, err := importMachines(map[string]interface{}{
 
157
                "version": 1,
 
158
                "machines": []interface{}{
 
159
                        minimalMachineMap("0"),
 
160
                        minimalMachineMap("1",
 
161
                                minimalMachineMap("1/lxc/0"),
 
162
                                minimalMachineMap("1/lxc/1"),
 
163
                        ),
 
164
                        minimalMachineMap("2",
 
165
                                minimalMachineMap("2/kvm/0",
 
166
                                        minimalMachineMap("2/kvm/0/lxc/0"),
 
167
                                        minimalMachineMap("2/kvm/0/lxc/1"),
 
168
                                ),
 
169
                        ),
 
170
                }})
 
171
        c.Assert(err, jc.ErrorIsNil)
 
172
        expected := []*machine{
 
173
                minimalMachine("0"),
 
174
                minimalMachine("1",
 
175
                        minimalMachine("1/lxc/0"),
 
176
                        minimalMachine("1/lxc/1"),
 
177
                ),
 
178
                minimalMachine("2",
 
179
                        minimalMachine("2/kvm/0",
 
180
                                minimalMachine("2/kvm/0/lxc/0"),
 
181
                                minimalMachine("2/kvm/0/lxc/1"),
 
182
                        ),
 
183
                ),
 
184
        }
 
185
        c.Assert(machines, jc.DeepEquals, expected)
 
186
}
 
187
 
 
188
func (s *MachineSerializationSuite) addNetworkPorts(m Machine) []NetworkPortsArgs {
 
189
        args := []NetworkPortsArgs{
 
190
                {
 
191
                        NetworkName: "storage",
 
192
                        OpenPorts: []PortRangeArgs{
 
193
                                {
 
194
                                        UnitName: "magic/0",
 
195
                                        FromPort: 1234,
 
196
                                        ToPort:   2345,
 
197
                                        Protocol: "tcp",
 
198
                                },
 
199
                        },
 
200
                }, {
 
201
                        NetworkName: "workload",
 
202
                        OpenPorts: []PortRangeArgs{
 
203
                                {
 
204
                                        UnitName: "unicorn/0",
 
205
                                        FromPort: 80,
 
206
                                        ToPort:   80,
 
207
                                        Protocol: "tcp",
 
208
                                },
 
209
                        },
 
210
                },
 
211
        }
 
212
        m.AddNetworkPorts(args[0])
 
213
        m.AddNetworkPorts(args[1])
 
214
        return args
 
215
}
 
216
 
 
217
func (s *MachineSerializationSuite) TestNetworkPorts(c *gc.C) {
 
218
        m := newMachine(s.machineArgs("42"))
 
219
        args := s.addNetworkPorts(m)
 
220
        ports := m.NetworkPorts()
 
221
        c.Assert(ports, gc.HasLen, 2)
 
222
        storage, workload := ports[0], ports[1]
 
223
        c.Assert(storage.NetworkName(), gc.Equals, "storage")
 
224
        c.Assert(workload.NetworkName(), gc.Equals, "workload")
 
225
        opened := storage.OpenPorts()
 
226
        c.Assert(opened, gc.HasLen, 1)
 
227
        s.AssertPortRange(c, opened[0], args[0].OpenPorts[0])
 
228
        opened = workload.OpenPorts()
 
229
        c.Assert(opened, gc.HasLen, 1)
 
230
        s.AssertPortRange(c, opened[0], args[1].OpenPorts[0])
 
231
}
 
232
 
 
233
func (s *MachineSerializationSuite) TestAnnotations(c *gc.C) {
 
234
        initial := minimalMachine("42")
 
235
        annotations := map[string]string{
 
236
                "string":  "value",
 
237
                "another": "one",
 
238
        }
 
239
        initial.SetAnnotations(annotations)
 
240
 
 
241
        machine := s.exportImport(c, initial)
 
242
        c.Assert(machine.Annotations(), jc.DeepEquals, annotations)
 
243
}
 
244
 
 
245
func (s *MachineSerializationSuite) TestConstraints(c *gc.C) {
 
246
        initial := minimalMachine("42")
 
247
        args := ConstraintsArgs{
 
248
                Architecture: "amd64",
 
249
                Memory:       8 * gig,
 
250
                RootDisk:     40 * gig,
 
251
        }
 
252
        initial.SetConstraints(args)
 
253
 
 
254
        machine := s.exportImport(c, initial)
 
255
        c.Assert(machine.Constraints(), jc.DeepEquals, newConstraints(args))
 
256
}
 
257
 
 
258
func (s *MachineSerializationSuite) exportImport(c *gc.C, machine_ *machine) *machine {
 
259
        initial := machines{
 
260
                Version:   1,
 
261
                Machines_: []*machine{machine_},
 
262
        }
 
263
 
 
264
        bytes, err := yaml.Marshal(initial)
 
265
        c.Assert(err, jc.ErrorIsNil)
 
266
 
 
267
        var source map[string]interface{}
 
268
        err = yaml.Unmarshal(bytes, &source)
 
269
        c.Assert(err, jc.ErrorIsNil)
 
270
 
 
271
        machines, err := importMachines(source)
 
272
        c.Assert(err, jc.ErrorIsNil)
 
273
        c.Assert(machines, gc.HasLen, 1)
 
274
        return machines[0]
 
275
}
 
276
 
 
277
func (s *MachineSerializationSuite) TestParsingSerializedData(c *gc.C) {
 
278
        // TODO: need to fully specify a machine.
 
279
        args := s.machineArgs("0")
 
280
        supported := []string{"kvm", "lxd"}
 
281
        args.SupportedContainers = &supported
 
282
        m := newMachine(args)
 
283
        m.SetTools(minimalAgentToolsArgs())
 
284
        m.SetStatus(minimalStatusArgs())
 
285
        m.SetInstance(minimalCloudInstanceArgs())
 
286
        s.addNetworkPorts(m)
 
287
 
 
288
        // Just use one set of address args for both machine and provider.
 
289
        addrArgs := []AddressArgs{
 
290
                {
 
291
                        Value: "10.0.0.10",
 
292
                        Type:  "special",
 
293
                }, {
 
294
                        Value: "10.1.2.3",
 
295
                        Type:  "other",
 
296
                },
 
297
        }
 
298
        m.SetAddresses(addrArgs, addrArgs)
 
299
        m.SetPreferredAddresses(addrArgs[0], addrArgs[1])
 
300
 
 
301
        // Make sure the machine is valid.
 
302
        c.Assert(m.Validate(), jc.ErrorIsNil)
 
303
 
 
304
        machine := s.exportImport(c, m)
 
305
        c.Assert(machine, jc.DeepEquals, m)
 
306
}
 
307
 
 
308
type CloudInstanceSerializationSuite struct {
 
309
        SerializationSuite
 
310
}
 
311
 
 
312
var _ = gc.Suite(&CloudInstanceSerializationSuite{})
 
313
 
 
314
func (s *CloudInstanceSerializationSuite) SetUpTest(c *gc.C) {
 
315
        s.importName = "cloudInstance"
 
316
        s.importFunc = func(m map[string]interface{}) (interface{}, error) {
 
317
                return importCloudInstance(m)
 
318
        }
 
319
}
 
320
 
 
321
func minimalCloudInstanceMap() map[interface{}]interface{} {
 
322
        return map[interface{}]interface{}{
 
323
                "version":     1,
 
324
                "instance-id": "instance id",
 
325
                "status":      "some status",
 
326
        }
 
327
}
 
328
 
 
329
func minimalCloudInstance() *cloudInstance {
 
330
        return newCloudInstance(minimalCloudInstanceArgs())
 
331
}
 
332
 
 
333
func minimalCloudInstanceArgs() CloudInstanceArgs {
 
334
        return CloudInstanceArgs{
 
335
                InstanceId: "instance id",
 
336
                Status:     "some status",
 
337
        }
 
338
}
 
339
 
 
340
func (s *CloudInstanceSerializationSuite) TestNewCloudInstance(c *gc.C) {
 
341
        // NOTE: using gig from package_test.go
 
342
        args := CloudInstanceArgs{
 
343
                InstanceId:       "instance id",
 
344
                Status:           "working",
 
345
                Architecture:     "amd64",
 
346
                Memory:           16 * gig,
 
347
                RootDisk:         200 * gig,
 
348
                CpuCores:         8,
 
349
                CpuPower:         4000,
 
350
                Tags:             []string{"much", "strong"},
 
351
                AvailabilityZone: "everywhere",
 
352
        }
 
353
 
 
354
        instance := newCloudInstance(args)
 
355
 
 
356
        c.Assert(instance.InstanceId(), gc.Equals, args.InstanceId)
 
357
        c.Assert(instance.Status(), gc.Equals, args.Status)
 
358
        c.Assert(instance.Architecture(), gc.Equals, args.Architecture)
 
359
        c.Assert(instance.Memory(), gc.Equals, args.Memory)
 
360
        c.Assert(instance.RootDisk(), gc.Equals, args.RootDisk)
 
361
        c.Assert(instance.CpuCores(), gc.Equals, args.CpuCores)
 
362
        c.Assert(instance.CpuPower(), gc.Equals, args.CpuPower)
 
363
        c.Assert(instance.AvailabilityZone(), gc.Equals, args.AvailabilityZone)
 
364
 
 
365
        // Before we check tags, modify args to make sure that the instance ones
 
366
        // don't change.
 
367
 
 
368
        args.Tags[0] = "weird"
 
369
        tags := instance.Tags()
 
370
        c.Assert(tags, jc.DeepEquals, []string{"much", "strong"})
 
371
 
 
372
        // Also, changing the tags returned, doesn't modify the instance
 
373
        tags[0] = "weird"
 
374
        c.Assert(instance.Tags(), jc.DeepEquals, []string{"much", "strong"})
 
375
}
 
376
 
 
377
func (s *CloudInstanceSerializationSuite) TestMinimalMatches(c *gc.C) {
 
378
        bytes, err := yaml.Marshal(minimalCloudInstance())
 
379
        c.Assert(err, jc.ErrorIsNil)
 
380
 
 
381
        var source map[interface{}]interface{}
 
382
        err = yaml.Unmarshal(bytes, &source)
 
383
        c.Assert(err, jc.ErrorIsNil)
 
384
        c.Assert(source, jc.DeepEquals, minimalCloudInstanceMap())
 
385
}
 
386
 
 
387
func (s *CloudInstanceSerializationSuite) TestParsingSerializedData(c *gc.C) {
 
388
        const MaxUint64 = 1<<64 - 1
 
389
        initial := newCloudInstance(CloudInstanceArgs{
 
390
                InstanceId:   "instance id",
 
391
                Status:       "working",
 
392
                Architecture: "amd64",
 
393
                Memory:       16 * gig,
 
394
                CpuPower:     MaxUint64,
 
395
                Tags:         []string{"much", "strong"},
 
396
        })
 
397
        bytes, err := yaml.Marshal(initial)
 
398
        c.Assert(err, jc.ErrorIsNil)
 
399
 
 
400
        var source map[string]interface{}
 
401
        err = yaml.Unmarshal(bytes, &source)
 
402
        c.Assert(err, jc.ErrorIsNil)
 
403
 
 
404
        instance, err := importCloudInstance(source)
 
405
        c.Assert(err, jc.ErrorIsNil)
 
406
        c.Assert(instance, jc.DeepEquals, initial)
 
407
}
 
408
 
 
409
type AgentToolsSerializationSuite struct {
 
410
        SerializationSuite
 
411
}
 
412
 
 
413
var _ = gc.Suite(&AgentToolsSerializationSuite{})
 
414
 
 
415
func (s *AgentToolsSerializationSuite) SetUpTest(c *gc.C) {
 
416
        s.importName = "agentTools"
 
417
        s.importFunc = func(m map[string]interface{}) (interface{}, error) {
 
418
                return importAgentTools(m)
 
419
        }
 
420
}
 
421
 
 
422
func (s *AgentToolsSerializationSuite) TestNewAgentTools(c *gc.C) {
 
423
        args := AgentToolsArgs{
 
424
                Version: version.MustParseBinary("3.4.5-trusty-amd64"),
 
425
                URL:     "some-url",
 
426
                SHA256:  "long-hash",
 
427
                Size:    123456789,
 
428
        }
 
429
        instance := newAgentTools(args)
 
430
 
 
431
        c.Assert(instance.Version(), gc.Equals, args.Version)
 
432
        c.Assert(instance.URL(), gc.Equals, args.URL)
 
433
        c.Assert(instance.SHA256(), gc.Equals, args.SHA256)
 
434
        c.Assert(instance.Size(), gc.Equals, args.Size)
 
435
}
 
436
 
 
437
func minimalAgentToolsMap() map[interface{}]interface{} {
 
438
        return map[interface{}]interface{}{
 
439
                "version":       1,
 
440
                "tools-version": "3.4.5-trusty-amd64",
 
441
                "url":           "some-url",
 
442
                "sha256":        "long-hash",
 
443
                "size":          123456789,
 
444
        }
 
445
}
 
446
 
 
447
func minimalAgentToolsArgs() AgentToolsArgs {
 
448
        return AgentToolsArgs{
 
449
                Version: version.MustParseBinary("3.4.5-trusty-amd64"),
 
450
                URL:     "some-url",
 
451
                SHA256:  "long-hash",
 
452
                Size:    123456789,
 
453
        }
 
454
}
 
455
 
 
456
func minimalAgentTools() *agentTools {
 
457
        return newAgentTools(minimalAgentToolsArgs())
 
458
}
 
459
 
 
460
func (s *AgentToolsSerializationSuite) TestMinimalMatches(c *gc.C) {
 
461
        bytes, err := yaml.Marshal(minimalAgentTools())
 
462
        c.Assert(err, jc.ErrorIsNil)
 
463
 
 
464
        var source map[interface{}]interface{}
 
465
        err = yaml.Unmarshal(bytes, &source)
 
466
        c.Assert(err, jc.ErrorIsNil)
 
467
        c.Assert(source, jc.DeepEquals, minimalAgentToolsMap())
 
468
}
 
469
 
 
470
func (s *AgentToolsSerializationSuite) TestParsingSerializedData(c *gc.C) {
 
471
        initial := newAgentTools(AgentToolsArgs{
 
472
                Version: version.MustParseBinary("2.0.4-trusty-amd64"),
 
473
                URL:     "some-url",
 
474
                SHA256:  "long-hash",
 
475
                Size:    123456789,
 
476
        })
 
477
        bytes, err := yaml.Marshal(initial)
 
478
        c.Assert(err, jc.ErrorIsNil)
 
479
 
 
480
        var source map[string]interface{}
 
481
        err = yaml.Unmarshal(bytes, &source)
 
482
        c.Assert(err, jc.ErrorIsNil)
 
483
 
 
484
        instance, err := importAgentTools(source)
 
485
        c.Assert(err, jc.ErrorIsNil)
 
486
        c.Assert(instance, jc.DeepEquals, initial)
 
487
}