~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/core/description/model_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 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package description
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        "time"
 
9
 
 
10
        "github.com/juju/errors"
 
11
        jc "github.com/juju/testing/checkers"
 
12
        "github.com/juju/version"
 
13
        gc "gopkg.in/check.v1"
 
14
        "gopkg.in/juju/names.v2"
 
15
        "gopkg.in/yaml.v2"
 
16
 
 
17
        "github.com/juju/juju/testing"
 
18
)
 
19
 
 
20
type ModelSerializationSuite struct {
 
21
        testing.BaseSuite
 
22
}
 
23
 
 
24
var _ = gc.Suite(&ModelSerializationSuite{})
 
25
 
 
26
func (*ModelSerializationSuite) TestNil(c *gc.C) {
 
27
        _, err := importModel(nil)
 
28
        c.Check(err, gc.ErrorMatches, "version: expected int, got nothing")
 
29
}
 
30
 
 
31
func (*ModelSerializationSuite) TestMissingVersion(c *gc.C) {
 
32
        _, err := importModel(map[string]interface{}{})
 
33
        c.Check(err, gc.ErrorMatches, "version: expected int, got nothing")
 
34
}
 
35
 
 
36
func (*ModelSerializationSuite) TestNonIntVersion(c *gc.C) {
 
37
        _, err := importModel(map[string]interface{}{
 
38
                "version": "hello",
 
39
        })
 
40
        c.Check(err.Error(), gc.Equals, `version: expected int, got string("hello")`)
 
41
}
 
42
 
 
43
func (*ModelSerializationSuite) TestUnknownVersion(c *gc.C) {
 
44
        _, err := importModel(map[string]interface{}{
 
45
                "version": 42,
 
46
        })
 
47
        c.Check(err.Error(), gc.Equals, `version 42 not valid`)
 
48
}
 
49
 
 
50
func (*ModelSerializationSuite) TestUpdateConfig(c *gc.C) {
 
51
        model := NewModel(ModelArgs{
 
52
                Config: map[string]interface{}{
 
53
                        "name": "awesome",
 
54
                        "uuid": "some-uuid",
 
55
                },
 
56
                CloudRegion: "some-region",
 
57
        })
 
58
        model.UpdateConfig(map[string]interface{}{
 
59
                "name": "something else",
 
60
                "key":  "value",
 
61
        })
 
62
        c.Assert(model.Config(), jc.DeepEquals, map[string]interface{}{
 
63
                "name": "something else",
 
64
                "uuid": "some-uuid",
 
65
                "key":  "value",
 
66
        })
 
67
}
 
68
 
 
69
func (s *ModelSerializationSuite) exportImport(c *gc.C, initial Model) Model {
 
70
        bytes, err := Serialize(initial)
 
71
        c.Assert(err, jc.ErrorIsNil)
 
72
        model, err := Deserialize(bytes)
 
73
        c.Assert(err, jc.ErrorIsNil)
 
74
        return model
 
75
}
 
76
 
 
77
func (s *ModelSerializationSuite) TestParsingYAML(c *gc.C) {
 
78
        args := ModelArgs{
 
79
                Owner: names.NewUserTag("magic"),
 
80
                Config: map[string]interface{}{
 
81
                        "name": "awesome",
 
82
                        "uuid": "some-uuid",
 
83
                },
 
84
                LatestToolsVersion: version.MustParse("2.0.1"),
 
85
                Blocks: map[string]string{
 
86
                        "all-changes": "locked down",
 
87
                },
 
88
        }
 
89
        initial := NewModel(args)
 
90
        adminUser := names.NewUserTag("admin@local")
 
91
        initial.AddUser(UserArgs{
 
92
                Name:        adminUser,
 
93
                CreatedBy:   adminUser,
 
94
                DateCreated: time.Date(2015, 10, 9, 12, 34, 56, 0, time.UTC),
 
95
        })
 
96
        addMinimalMachine(initial, "0")
 
97
        addMinimalApplication(initial)
 
98
        model := s.exportImport(c, initial)
 
99
 
 
100
        c.Assert(model.Owner(), gc.Equals, args.Owner)
 
101
        c.Assert(model.Tag().Id(), gc.Equals, "some-uuid")
 
102
        c.Assert(model.Config(), jc.DeepEquals, args.Config)
 
103
        c.Assert(model.LatestToolsVersion(), gc.Equals, args.LatestToolsVersion)
 
104
        c.Assert(model.Blocks(), jc.DeepEquals, args.Blocks)
 
105
        users := model.Users()
 
106
        c.Assert(users, gc.HasLen, 1)
 
107
        c.Assert(users[0].Name(), gc.Equals, adminUser)
 
108
        machines := model.Machines()
 
109
        c.Assert(machines, gc.HasLen, 1)
 
110
        c.Assert(machines[0].Id(), gc.Equals, "0")
 
111
        applications := model.Applications()
 
112
        c.Assert(applications, gc.HasLen, 1)
 
113
        c.Assert(applications[0].Name(), gc.Equals, "ubuntu")
 
114
}
 
115
 
 
116
func (s *ModelSerializationSuite) TestParsingOptionals(c *gc.C) {
 
117
        args := ModelArgs{
 
118
                Owner: names.NewUserTag("magic"),
 
119
                Config: map[string]interface{}{
 
120
                        "name": "awesome",
 
121
                        "uuid": "some-uuid",
 
122
                },
 
123
        }
 
124
        initial := NewModel(args)
 
125
        model := s.exportImport(c, initial)
 
126
        c.Assert(model.LatestToolsVersion(), gc.Equals, version.Zero)
 
127
}
 
128
 
 
129
func (s *ModelSerializationSuite) TestAnnotations(c *gc.C) {
 
130
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
131
        annotations := map[string]string{
 
132
                "string":  "value",
 
133
                "another": "one",
 
134
        }
 
135
        initial.SetAnnotations(annotations)
 
136
 
 
137
        bytes, err := yaml.Marshal(initial)
 
138
        c.Assert(err, jc.ErrorIsNil)
 
139
 
 
140
        model, err := Deserialize(bytes)
 
141
        c.Assert(err, jc.ErrorIsNil)
 
142
        c.Assert(model.Annotations(), jc.DeepEquals, annotations)
 
143
}
 
144
 
 
145
func (s *ModelSerializationSuite) TestSequences(c *gc.C) {
 
146
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
147
        initial.SetSequence("machine", 4)
 
148
        initial.SetSequence("application-foo", 3)
 
149
        initial.SetSequence("application-bar", 1)
 
150
        bytes, err := yaml.Marshal(initial)
 
151
        c.Assert(err, jc.ErrorIsNil)
 
152
 
 
153
        model, err := Deserialize(bytes)
 
154
        c.Assert(err, jc.ErrorIsNil)
 
155
 
 
156
        c.Assert(model.Sequences(), jc.DeepEquals, map[string]int{
 
157
                "machine":         4,
 
158
                "application-foo": 3,
 
159
                "application-bar": 1,
 
160
        })
 
161
}
 
162
 
 
163
func (s *ModelSerializationSuite) TestConstraints(c *gc.C) {
 
164
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
165
        args := ConstraintsArgs{
 
166
                Architecture: "amd64",
 
167
                Memory:       8 * gig,
 
168
        }
 
169
        initial.SetConstraints(args)
 
170
 
 
171
        bytes, err := yaml.Marshal(initial)
 
172
        c.Assert(err, jc.ErrorIsNil)
 
173
 
 
174
        model, err := Deserialize(bytes)
 
175
        c.Assert(err, jc.ErrorIsNil)
 
176
        c.Assert(model.Constraints(), jc.DeepEquals, newConstraints(args))
 
177
}
 
178
 
 
179
func (*ModelSerializationSuite) TestModelValidation(c *gc.C) {
 
180
        model := NewModel(ModelArgs{})
 
181
        err := model.Validate()
 
182
        c.Assert(err, gc.ErrorMatches, "missing model owner not valid")
 
183
        c.Assert(err, jc.Satisfies, errors.IsNotValid)
 
184
}
 
185
 
 
186
func (*ModelSerializationSuite) TestModelValidationChecksMachines(c *gc.C) {
 
187
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner"), CloudRegion: "some-region"})
 
188
        model.AddMachine(MachineArgs{})
 
189
        err := model.Validate()
 
190
        c.Assert(err, gc.ErrorMatches, "machine missing id not valid")
 
191
        c.Assert(err, jc.Satisfies, errors.IsNotValid)
 
192
}
 
193
 
 
194
func (s *ModelSerializationSuite) addMachineToModel(model Model, id string) Machine {
 
195
        machine := model.AddMachine(MachineArgs{Id: names.NewMachineTag(id)})
 
196
        machine.SetInstance(CloudInstanceArgs{InstanceId: "magic"})
 
197
        machine.SetTools(minimalAgentToolsArgs())
 
198
        machine.SetStatus(minimalStatusArgs())
 
199
        return machine
 
200
}
 
201
 
 
202
func (s *ModelSerializationSuite) TestModelValidationChecksMachinesGood(c *gc.C) {
 
203
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner"), CloudRegion: "some-region"})
 
204
        s.addMachineToModel(model, "0")
 
205
        err := model.Validate()
 
206
        c.Assert(err, jc.ErrorIsNil)
 
207
}
 
208
 
 
209
func (s *ModelSerializationSuite) TestModelValidationChecksOpenPortsUnits(c *gc.C) {
 
210
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner"), CloudRegion: "some-region"})
 
211
        machine := s.addMachineToModel(model, "0")
 
212
        machine.AddOpenedPorts(OpenedPortsArgs{
 
213
                OpenedPorts: []PortRangeArgs{
 
214
                        {
 
215
                                UnitName: "missing/0",
 
216
                                FromPort: 8080,
 
217
                                ToPort:   8080,
 
218
                                Protocol: "tcp",
 
219
                        },
 
220
                },
 
221
        })
 
222
        err := model.Validate()
 
223
        c.Assert(err.Error(), gc.Equals, "unknown unit names in open ports: [missing/0]")
 
224
}
 
225
 
 
226
func (*ModelSerializationSuite) TestModelValidationChecksApplications(c *gc.C) {
 
227
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner"), CloudRegion: "some-region"})
 
228
        model.AddApplication(ApplicationArgs{})
 
229
        err := model.Validate()
 
230
        c.Assert(err, gc.ErrorMatches, "application missing name not valid")
 
231
        c.Assert(err, jc.Satisfies, errors.IsNotValid)
 
232
}
 
233
 
 
234
func (s *ModelSerializationSuite) addApplicationToModel(model Model, name string, numUnits int) Application {
 
235
        application := model.AddApplication(ApplicationArgs{
 
236
                Tag:                names.NewApplicationTag(name),
 
237
                Settings:           map[string]interface{}{},
 
238
                LeadershipSettings: map[string]interface{}{},
 
239
        })
 
240
        application.SetStatus(minimalStatusArgs())
 
241
        for i := 0; i < numUnits; i++ {
 
242
                // The index i is used as both the machine id and the unit id.
 
243
                // A happy coincidence.
 
244
                machine := s.addMachineToModel(model, fmt.Sprint(i))
 
245
                unit := application.AddUnit(UnitArgs{
 
246
                        Tag:     names.NewUnitTag(fmt.Sprintf("%s/%d", name, i)),
 
247
                        Machine: machine.Tag(),
 
248
                })
 
249
                unit.SetTools(minimalAgentToolsArgs())
 
250
                unit.SetAgentStatus(minimalStatusArgs())
 
251
                unit.SetWorkloadStatus(minimalStatusArgs())
 
252
        }
 
253
 
 
254
        return application
 
255
}
 
256
 
 
257
func (s *ModelSerializationSuite) wordpressModel() (Model, Endpoint, Endpoint) {
 
258
        model := NewModel(ModelArgs{
 
259
                Owner: names.NewUserTag("owner"),
 
260
                Config: map[string]interface{}{
 
261
                        "uuid": "some-uuid",
 
262
                },
 
263
                CloudRegion: "some-region",
 
264
        })
 
265
        s.addApplicationToModel(model, "wordpress", 2)
 
266
        s.addApplicationToModel(model, "mysql", 1)
 
267
 
 
268
        // Add a relation between wordpress and mysql.
 
269
        rel := model.AddRelation(RelationArgs{
 
270
                Id:  42,
 
271
                Key: "special key",
 
272
        })
 
273
        wordpressEndpoint := rel.AddEndpoint(EndpointArgs{
 
274
                ApplicationName: "wordpress",
 
275
                Name:            "db",
 
276
                // Ignoring other aspects of endpoints.
 
277
        })
 
278
        mysqlEndpoint := rel.AddEndpoint(EndpointArgs{
 
279
                ApplicationName: "mysql",
 
280
                Name:            "mysql",
 
281
                // Ignoring other aspects of endpoints.
 
282
        })
 
283
        return model, wordpressEndpoint, mysqlEndpoint
 
284
}
 
285
 
 
286
func (s *ModelSerializationSuite) wordpressModelWithSettings() Model {
 
287
        model, wordpressEndpoint, mysqlEndpoint := s.wordpressModel()
 
288
 
 
289
        wordpressEndpoint.SetUnitSettings("wordpress/0", map[string]interface{}{
 
290
                "key": "value",
 
291
        })
 
292
        wordpressEndpoint.SetUnitSettings("wordpress/1", map[string]interface{}{
 
293
                "key": "value",
 
294
        })
 
295
        mysqlEndpoint.SetUnitSettings("mysql/0", map[string]interface{}{
 
296
                "key": "value",
 
297
        })
 
298
        return model
 
299
}
 
300
 
 
301
func (s *ModelSerializationSuite) TestModelValidationChecksRelationsMissingSettings(c *gc.C) {
 
302
        model, _, _ := s.wordpressModel()
 
303
        err := model.Validate()
 
304
        c.Assert(err, gc.ErrorMatches, "missing relation settings for units \\[wordpress/0 wordpress/1\\] in relation 42")
 
305
}
 
306
 
 
307
func (s *ModelSerializationSuite) TestModelValidationChecksRelationsMissingSettings2(c *gc.C) {
 
308
        model, wordpressEndpoint, _ := s.wordpressModel()
 
309
 
 
310
        wordpressEndpoint.SetUnitSettings("wordpress/0", map[string]interface{}{
 
311
                "key": "value",
 
312
        })
 
313
        wordpressEndpoint.SetUnitSettings("wordpress/1", map[string]interface{}{
 
314
                "key": "value",
 
315
        })
 
316
        err := model.Validate()
 
317
        c.Assert(err, gc.ErrorMatches, "missing relation settings for units \\[mysql/0\\] in relation 42")
 
318
}
 
319
 
 
320
func (s *ModelSerializationSuite) TestModelValidationChecksRelations(c *gc.C) {
 
321
        model := s.wordpressModelWithSettings()
 
322
        err := model.Validate()
 
323
        c.Assert(err, jc.ErrorIsNil)
 
324
}
 
325
 
 
326
func (s *ModelSerializationSuite) TestModelSerializationWithRelations(c *gc.C) {
 
327
        initial := s.wordpressModelWithSettings()
 
328
        bytes, err := yaml.Marshal(initial)
 
329
        c.Assert(err, jc.ErrorIsNil)
 
330
        model, err := Deserialize(bytes)
 
331
        c.Assert(err, jc.ErrorIsNil)
 
332
        c.Assert(model, jc.DeepEquals, initial)
 
333
}
 
334
 
 
335
func (s *ModelSerializationSuite) TestModelValidationChecksSubnets(c *gc.C) {
 
336
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
337
        model.AddSubnet(SubnetArgs{CIDR: "10.0.0.0/24", SpaceName: "foo"})
 
338
        model.AddSubnet(SubnetArgs{CIDR: "10.0.1.0/24"})
 
339
        err := model.Validate()
 
340
        c.Assert(err, gc.ErrorMatches, `subnet "10.0.0.0/24" references non-existent space "foo"`)
 
341
        model.AddSpace(SpaceArgs{Name: "foo"})
 
342
        err = model.Validate()
 
343
        c.Assert(err, jc.ErrorIsNil)
 
344
}
 
345
 
 
346
func (s *ModelSerializationSuite) TestModelValidationChecksAddressMachineID(c *gc.C) {
 
347
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
348
        model.AddIPAddress(IPAddressArgs{Value: "192.168.1.0", MachineID: "42"})
 
349
        err := model.Validate()
 
350
        c.Assert(err, gc.ErrorMatches, `ip address "192.168.1.0" references non-existent machine "42"`)
 
351
}
 
352
 
 
353
func (s *ModelSerializationSuite) TestModelValidationChecksAddressDeviceName(c *gc.C) {
 
354
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
355
        args := IPAddressArgs{Value: "192.168.1.0", MachineID: "42", DeviceName: "foo"}
 
356
        model.AddIPAddress(args)
 
357
        s.addMachineToModel(model, "42")
 
358
        err := model.Validate()
 
359
        c.Assert(err, gc.ErrorMatches, `ip address "192.168.1.0" references non-existent device "foo"`)
 
360
}
 
361
 
 
362
func (s *ModelSerializationSuite) TestModelValidationChecksAddressValueEmpty(c *gc.C) {
 
363
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
364
        args := IPAddressArgs{MachineID: "42", DeviceName: "foo"}
 
365
        model.AddIPAddress(args)
 
366
        s.addMachineToModel(model, "42")
 
367
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
368
        err := model.Validate()
 
369
        c.Assert(err, gc.ErrorMatches, `ip address has invalid value ""`)
 
370
}
 
371
 
 
372
func (s *ModelSerializationSuite) TestModelValidationChecksAddressValueInvalid(c *gc.C) {
 
373
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
374
        args := IPAddressArgs{MachineID: "42", DeviceName: "foo", Value: "foobar"}
 
375
        model.AddIPAddress(args)
 
376
        s.addMachineToModel(model, "42")
 
377
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
378
        err := model.Validate()
 
379
        c.Assert(err, gc.ErrorMatches, `ip address has invalid value "foobar"`)
 
380
}
 
381
 
 
382
func (s *ModelSerializationSuite) TestModelValidationChecksAddressSubnetEmpty(c *gc.C) {
 
383
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
384
        args := IPAddressArgs{MachineID: "42", DeviceName: "foo", Value: "192.168.1.1"}
 
385
        model.AddIPAddress(args)
 
386
        s.addMachineToModel(model, "42")
 
387
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
388
        err := model.Validate()
 
389
        c.Assert(err, gc.ErrorMatches, `ip address "192.168.1.1" has empty subnet CIDR`)
 
390
}
 
391
 
 
392
func (s *ModelSerializationSuite) TestModelValidationChecksAddressSubnetInvalid(c *gc.C) {
 
393
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
394
        args := IPAddressArgs{
 
395
                MachineID:  "42",
 
396
                DeviceName: "foo",
 
397
                Value:      "192.168.1.1",
 
398
                SubnetCIDR: "foo",
 
399
        }
 
400
        model.AddIPAddress(args)
 
401
        s.addMachineToModel(model, "42")
 
402
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
403
        err := model.Validate()
 
404
        c.Assert(err, gc.ErrorMatches, `ip address "192.168.1.1" has invalid subnet CIDR "foo"`)
 
405
}
 
406
 
 
407
func (s *ModelSerializationSuite) TestModelValidationChecksAddressSucceeds(c *gc.C) {
 
408
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
409
        args := IPAddressArgs{
 
410
                MachineID:  "42",
 
411
                DeviceName: "foo",
 
412
                Value:      "192.168.1.1",
 
413
                SubnetCIDR: "192.168.1.0/24",
 
414
        }
 
415
        model.AddIPAddress(args)
 
416
        s.addMachineToModel(model, "42")
 
417
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
418
        err := model.Validate()
 
419
        c.Assert(err, jc.ErrorIsNil)
 
420
}
 
421
 
 
422
func (s *ModelSerializationSuite) TestModelValidationChecksAddressGatewayAddressInvalid(c *gc.C) {
 
423
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
424
        args := IPAddressArgs{
 
425
                MachineID:      "42",
 
426
                DeviceName:     "foo",
 
427
                Value:          "192.168.1.1",
 
428
                SubnetCIDR:     "192.168.1.0/24",
 
429
                GatewayAddress: "foo",
 
430
        }
 
431
        model.AddIPAddress(args)
 
432
        s.addMachineToModel(model, "42")
 
433
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
434
        err := model.Validate()
 
435
        c.Assert(err, gc.ErrorMatches, `ip address "192.168.1.1" has invalid gateway address "foo"`)
 
436
}
 
437
 
 
438
func (s *ModelSerializationSuite) TestModelValidationChecksAddressGatewayAddressValid(c *gc.C) {
 
439
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
440
        args := IPAddressArgs{
 
441
                MachineID:      "42",
 
442
                DeviceName:     "foo",
 
443
                Value:          "192.168.1.2",
 
444
                SubnetCIDR:     "192.168.1.0/24",
 
445
                GatewayAddress: "192.168.1.1",
 
446
        }
 
447
        model.AddIPAddress(args)
 
448
        s.addMachineToModel(model, "42")
 
449
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
450
        err := model.Validate()
 
451
        c.Assert(err, jc.ErrorIsNil)
 
452
}
 
453
 
 
454
func (s *ModelSerializationSuite) TestModelValidationChecksLinkLayerDeviceMachineId(c *gc.C) {
 
455
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
456
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo", MachineID: "42"})
 
457
        err := model.Validate()
 
458
        c.Assert(err, gc.ErrorMatches, `device "foo" references non-existent machine "42"`)
 
459
        s.addMachineToModel(model, "42")
 
460
        err = model.Validate()
 
461
        c.Assert(err, jc.ErrorIsNil)
 
462
}
 
463
 
 
464
func (s *ModelSerializationSuite) TestModelValidationChecksLinkLayerName(c *gc.C) {
 
465
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
466
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{MachineID: "42"})
 
467
        s.addMachineToModel(model, "42")
 
468
        err := model.Validate()
 
469
        c.Assert(err, gc.ErrorMatches, "device has empty name.*")
 
470
}
 
471
 
 
472
func (s *ModelSerializationSuite) TestModelValidationChecksLinkLayerMACAddress(c *gc.C) {
 
473
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
474
        args := LinkLayerDeviceArgs{MachineID: "42", Name: "foo", MACAddress: "DEADBEEF"}
 
475
        model.AddLinkLayerDevice(args)
 
476
        s.addMachineToModel(model, "42")
 
477
        err := model.Validate()
 
478
        c.Assert(err, gc.ErrorMatches, `device "foo" has invalid MACAddress "DEADBEEF"`)
 
479
}
 
480
 
 
481
func (s *ModelSerializationSuite) TestModelValidationChecksParentExists(c *gc.C) {
 
482
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
483
        args := LinkLayerDeviceArgs{MachineID: "42", Name: "foo", ParentName: "bar", MACAddress: "01:23:45:67:89:ab"}
 
484
        model.AddLinkLayerDevice(args)
 
485
        s.addMachineToModel(model, "42")
 
486
        err := model.Validate()
 
487
        c.Assert(err, gc.ErrorMatches, `device "foo" has non-existent parent "bar"`)
 
488
        model.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "bar", MachineID: "42"})
 
489
        err = model.Validate()
 
490
        c.Assert(err, jc.ErrorIsNil)
 
491
}
 
492
 
 
493
func (s *ModelSerializationSuite) TestModelValidationChecksParentIsNotItself(c *gc.C) {
 
494
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
495
        args := LinkLayerDeviceArgs{MachineID: "42", Name: "foo", ParentName: "foo"}
 
496
        model.AddLinkLayerDevice(args)
 
497
        s.addMachineToModel(model, "42")
 
498
        err := model.Validate()
 
499
        c.Assert(err, gc.ErrorMatches, `device "foo" is its own parent`)
 
500
}
 
501
 
 
502
func (s *ModelSerializationSuite) TestModelValidationChecksParentIsABridge(c *gc.C) {
 
503
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
504
        args := LinkLayerDeviceArgs{MachineID: "42", Name: "foo", ParentName: "m#43#d#bar"}
 
505
        model.AddLinkLayerDevice(args)
 
506
        args2 := LinkLayerDeviceArgs{MachineID: "43", Name: "bar"}
 
507
        model.AddLinkLayerDevice(args2)
 
508
        s.addMachineToModel(model, "42")
 
509
        s.addMachineToModel(model, "43")
 
510
        err := model.Validate()
 
511
        c.Assert(err, gc.ErrorMatches, `device "foo" on a container but not a bridge`)
 
512
}
 
513
 
 
514
func (s *ModelSerializationSuite) TestModelValidationChecksChildDeviceContained(c *gc.C) {
 
515
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
516
        args := LinkLayerDeviceArgs{MachineID: "42", Name: "foo", ParentName: "m#43#d#bar"}
 
517
        model.AddLinkLayerDevice(args)
 
518
        args2 := LinkLayerDeviceArgs{MachineID: "43", Name: "bar", Type: "bridge"}
 
519
        model.AddLinkLayerDevice(args2)
 
520
        s.addMachineToModel(model, "42")
 
521
        s.addMachineToModel(model, "43")
 
522
        err := model.Validate()
 
523
        c.Assert(err, gc.ErrorMatches, `ParentName "m#43#d#bar" for non-container machine "42"`)
 
524
}
 
525
 
 
526
func (s *ModelSerializationSuite) TestModelValidationChecksParentOnHost(c *gc.C) {
 
527
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
528
        args := LinkLayerDeviceArgs{MachineID: "41/lxd/0", Name: "foo", ParentName: "m#43#d#bar"}
 
529
        model.AddLinkLayerDevice(args)
 
530
        args2 := LinkLayerDeviceArgs{MachineID: "43", Name: "bar", Type: "bridge"}
 
531
        model.AddLinkLayerDevice(args2)
 
532
        machine := s.addMachineToModel(model, "41")
 
533
        container := machine.AddContainer(MachineArgs{Id: names.NewMachineTag("41/lxd/0")})
 
534
        container.SetInstance(CloudInstanceArgs{InstanceId: "magic"})
 
535
        container.SetTools(minimalAgentToolsArgs())
 
536
        container.SetStatus(minimalStatusArgs())
 
537
        s.addMachineToModel(model, "43")
 
538
        err := model.Validate()
 
539
        c.Assert(err, gc.ErrorMatches, `parent machine of device "foo" not host machine "41"`)
 
540
}
 
541
 
 
542
func (s *ModelSerializationSuite) TestModelValidationLinkLayerDeviceContainer(c *gc.C) {
 
543
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
544
        args := LinkLayerDeviceArgs{MachineID: "43/lxd/0", Name: "foo", ParentName: "m#43#d#bar"}
 
545
        model.AddLinkLayerDevice(args)
 
546
        args2 := LinkLayerDeviceArgs{MachineID: "43", Name: "bar", Type: "bridge"}
 
547
        model.AddLinkLayerDevice(args2)
 
548
        machine := s.addMachineToModel(model, "43")
 
549
        container := machine.AddContainer(MachineArgs{Id: names.NewMachineTag("43/lxd/0")})
 
550
        container.SetInstance(CloudInstanceArgs{InstanceId: "magic"})
 
551
        container.SetTools(minimalAgentToolsArgs())
 
552
        container.SetStatus(minimalStatusArgs())
 
553
        err := model.Validate()
 
554
        c.Assert(err, jc.ErrorIsNil)
 
555
}
 
556
 
 
557
func (s *ModelSerializationSuite) TestSpaces(c *gc.C) {
 
558
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
559
        space := initial.AddSpace(SpaceArgs{Name: "special"})
 
560
        c.Assert(space.Name(), gc.Equals, "special")
 
561
        spaces := initial.Spaces()
 
562
        c.Assert(spaces, gc.HasLen, 1)
 
563
        c.Assert(spaces[0], gc.Equals, space)
 
564
 
 
565
        bytes, err := yaml.Marshal(initial)
 
566
        c.Assert(err, jc.ErrorIsNil)
 
567
 
 
568
        model, err := Deserialize(bytes)
 
569
        c.Assert(err, jc.ErrorIsNil)
 
570
        c.Assert(model.Spaces(), jc.DeepEquals, spaces)
 
571
 
 
572
}
 
573
 
 
574
func (s *ModelSerializationSuite) TestLinkLayerDevice(c *gc.C) {
 
575
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
576
        device := initial.AddLinkLayerDevice(LinkLayerDeviceArgs{Name: "foo"})
 
577
        c.Assert(device.Name(), gc.Equals, "foo")
 
578
        devices := initial.LinkLayerDevices()
 
579
        c.Assert(devices, gc.HasLen, 1)
 
580
        c.Assert(devices[0], jc.DeepEquals, device)
 
581
 
 
582
        bytes, err := yaml.Marshal(initial)
 
583
        c.Assert(err, jc.ErrorIsNil)
 
584
 
 
585
        model, err := Deserialize(bytes)
 
586
        c.Assert(err, jc.ErrorIsNil)
 
587
        c.Assert(model.LinkLayerDevices(), jc.DeepEquals, devices)
 
588
}
 
589
 
 
590
func (s *ModelSerializationSuite) TestSubnets(c *gc.C) {
 
591
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
592
        subnet := initial.AddSubnet(SubnetArgs{CIDR: "10.0.0.0/24"})
 
593
        c.Assert(subnet.CIDR(), gc.Equals, "10.0.0.0/24")
 
594
        subnets := initial.Subnets()
 
595
        c.Assert(subnets, gc.HasLen, 1)
 
596
        c.Assert(subnets[0], jc.DeepEquals, subnet)
 
597
 
 
598
        bytes, err := yaml.Marshal(initial)
 
599
        c.Assert(err, jc.ErrorIsNil)
 
600
 
 
601
        model, err := Deserialize(bytes)
 
602
        c.Assert(err, jc.ErrorIsNil)
 
603
        c.Assert(model.Subnets(), jc.DeepEquals, subnets)
 
604
}
 
605
 
 
606
func (s *ModelSerializationSuite) TestIPAddress(c *gc.C) {
 
607
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
608
        addr := initial.AddIPAddress(IPAddressArgs{Value: "10.0.0.4"})
 
609
        c.Assert(addr.Value(), gc.Equals, "10.0.0.4")
 
610
        addresses := initial.IPAddresses()
 
611
        c.Assert(addresses, gc.HasLen, 1)
 
612
        c.Assert(addresses[0], jc.DeepEquals, addr)
 
613
 
 
614
        bytes, err := yaml.Marshal(initial)
 
615
        c.Assert(err, jc.ErrorIsNil)
 
616
 
 
617
        model, err := Deserialize(bytes)
 
618
        c.Assert(err, jc.ErrorIsNil)
 
619
        c.Assert(model.IPAddresses(), jc.DeepEquals, addresses)
 
620
}
 
621
 
 
622
func (s *ModelSerializationSuite) TestSSHHostKey(c *gc.C) {
 
623
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
624
        key := initial.AddSSHHostKey(SSHHostKeyArgs{MachineID: "foo"})
 
625
        c.Assert(key.MachineID(), gc.Equals, "foo")
 
626
        keys := initial.SSHHostKeys()
 
627
        c.Assert(keys, gc.HasLen, 1)
 
628
        c.Assert(keys[0], jc.DeepEquals, key)
 
629
 
 
630
        bytes, err := yaml.Marshal(initial)
 
631
        c.Assert(err, jc.ErrorIsNil)
 
632
 
 
633
        model, err := Deserialize(bytes)
 
634
        c.Assert(err, jc.ErrorIsNil)
 
635
        c.Assert(model.SSHHostKeys(), jc.DeepEquals, keys)
 
636
}
 
637
 
 
638
func (s *ModelSerializationSuite) TestVolumeValidation(c *gc.C) {
 
639
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
640
        model.AddVolume(testVolumeArgs())
 
641
        err := model.Validate()
 
642
        c.Assert(err, gc.ErrorMatches, `volume\[0\]: volume "1234" missing status not valid`)
 
643
}
 
644
 
 
645
func (s *ModelSerializationSuite) TestVolumes(c *gc.C) {
 
646
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
647
        volume := initial.AddVolume(testVolumeArgs())
 
648
        volume.SetStatus(minimalStatusArgs())
 
649
        volumes := initial.Volumes()
 
650
        c.Assert(volumes, gc.HasLen, 1)
 
651
        c.Assert(volumes[0], gc.Equals, volume)
 
652
 
 
653
        bytes, err := yaml.Marshal(initial)
 
654
        c.Assert(err, jc.ErrorIsNil)
 
655
 
 
656
        model, err := Deserialize(bytes)
 
657
        c.Assert(err, jc.ErrorIsNil)
 
658
        c.Assert(model.Volumes(), jc.DeepEquals, volumes)
 
659
}
 
660
 
 
661
func (s *ModelSerializationSuite) TestFilesystemValidation(c *gc.C) {
 
662
        model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
663
        model.AddFilesystem(testFilesystemArgs())
 
664
        err := model.Validate()
 
665
        c.Assert(err, gc.ErrorMatches, `filesystem\[0\]: filesystem "1234" missing status not valid`)
 
666
}
 
667
 
 
668
func (s *ModelSerializationSuite) TestFilesystems(c *gc.C) {
 
669
        initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
 
670
        filesystem := initial.AddFilesystem(testFilesystemArgs())
 
671
        filesystem.SetStatus(minimalStatusArgs())
 
672
        filesystem.AddAttachment(testFilesystemAttachmentArgs())
 
673
        filesystems := initial.Filesystems()
 
674
        c.Assert(filesystems, gc.HasLen, 1)
 
675
        c.Assert(filesystems[0], gc.Equals, filesystem)
 
676
 
 
677
        bytes, err := yaml.Marshal(initial)
 
678
        c.Assert(err, jc.ErrorIsNil)
 
679
 
 
680
        model, err := Deserialize(bytes)
 
681
        c.Assert(err, jc.ErrorIsNil)
 
682
        c.Assert(model.Filesystems(), jc.DeepEquals, filesystems)
 
683
}