1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
"github.com/juju/errors"
11
jc "github.com/juju/testing/checkers"
12
"github.com/juju/version"
13
gc "gopkg.in/check.v1"
14
"gopkg.in/juju/names.v2"
17
"github.com/juju/juju/testing"
20
type ModelSerializationSuite struct {
24
var _ = gc.Suite(&ModelSerializationSuite{})
26
func (*ModelSerializationSuite) TestNil(c *gc.C) {
27
_, err := importModel(nil)
28
c.Check(err, gc.ErrorMatches, "version: expected int, got nothing")
31
func (*ModelSerializationSuite) TestMissingVersion(c *gc.C) {
32
_, err := importModel(map[string]interface{}{})
33
c.Check(err, gc.ErrorMatches, "version: expected int, got nothing")
36
func (*ModelSerializationSuite) TestNonIntVersion(c *gc.C) {
37
_, err := importModel(map[string]interface{}{
40
c.Check(err.Error(), gc.Equals, `version: expected int, got string("hello")`)
43
func (*ModelSerializationSuite) TestUnknownVersion(c *gc.C) {
44
_, err := importModel(map[string]interface{}{
47
c.Check(err.Error(), gc.Equals, `version 42 not valid`)
50
func (*ModelSerializationSuite) TestUpdateConfig(c *gc.C) {
51
model := NewModel(ModelArgs{
52
Config: map[string]interface{}{
56
CloudRegion: "some-region",
58
model.UpdateConfig(map[string]interface{}{
59
"name": "something else",
62
c.Assert(model.Config(), jc.DeepEquals, map[string]interface{}{
63
"name": "something else",
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)
77
func (s *ModelSerializationSuite) TestParsingYAML(c *gc.C) {
79
Owner: names.NewUserTag("magic"),
80
Config: map[string]interface{}{
84
LatestToolsVersion: version.MustParse("2.0.1"),
85
Blocks: map[string]string{
86
"all-changes": "locked down",
89
initial := NewModel(args)
90
adminUser := names.NewUserTag("admin@local")
91
initial.AddUser(UserArgs{
94
DateCreated: time.Date(2015, 10, 9, 12, 34, 56, 0, time.UTC),
96
addMinimalMachine(initial, "0")
97
addMinimalApplication(initial)
98
model := s.exportImport(c, initial)
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")
116
func (s *ModelSerializationSuite) TestParsingOptionals(c *gc.C) {
118
Owner: names.NewUserTag("magic"),
119
Config: map[string]interface{}{
124
initial := NewModel(args)
125
model := s.exportImport(c, initial)
126
c.Assert(model.LatestToolsVersion(), gc.Equals, version.Zero)
129
func (s *ModelSerializationSuite) TestAnnotations(c *gc.C) {
130
initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
131
annotations := map[string]string{
135
initial.SetAnnotations(annotations)
137
bytes, err := yaml.Marshal(initial)
138
c.Assert(err, jc.ErrorIsNil)
140
model, err := Deserialize(bytes)
141
c.Assert(err, jc.ErrorIsNil)
142
c.Assert(model.Annotations(), jc.DeepEquals, annotations)
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)
153
model, err := Deserialize(bytes)
154
c.Assert(err, jc.ErrorIsNil)
156
c.Assert(model.Sequences(), jc.DeepEquals, map[string]int{
158
"application-foo": 3,
159
"application-bar": 1,
163
func (s *ModelSerializationSuite) TestConstraints(c *gc.C) {
164
initial := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
165
args := ConstraintsArgs{
166
Architecture: "amd64",
169
initial.SetConstraints(args)
171
bytes, err := yaml.Marshal(initial)
172
c.Assert(err, jc.ErrorIsNil)
174
model, err := Deserialize(bytes)
175
c.Assert(err, jc.ErrorIsNil)
176
c.Assert(model.Constraints(), jc.DeepEquals, newConstraints(args))
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)
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)
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())
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)
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{
215
UnitName: "missing/0",
222
err := model.Validate()
223
c.Assert(err.Error(), gc.Equals, "unknown unit names in open ports: [missing/0]")
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)
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{}{},
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(),
249
unit.SetTools(minimalAgentToolsArgs())
250
unit.SetAgentStatus(minimalStatusArgs())
251
unit.SetWorkloadStatus(minimalStatusArgs())
257
func (s *ModelSerializationSuite) wordpressModel() (Model, Endpoint, Endpoint) {
258
model := NewModel(ModelArgs{
259
Owner: names.NewUserTag("owner"),
260
Config: map[string]interface{}{
263
CloudRegion: "some-region",
265
s.addApplicationToModel(model, "wordpress", 2)
266
s.addApplicationToModel(model, "mysql", 1)
268
// Add a relation between wordpress and mysql.
269
rel := model.AddRelation(RelationArgs{
273
wordpressEndpoint := rel.AddEndpoint(EndpointArgs{
274
ApplicationName: "wordpress",
276
// Ignoring other aspects of endpoints.
278
mysqlEndpoint := rel.AddEndpoint(EndpointArgs{
279
ApplicationName: "mysql",
281
// Ignoring other aspects of endpoints.
283
return model, wordpressEndpoint, mysqlEndpoint
286
func (s *ModelSerializationSuite) wordpressModelWithSettings() Model {
287
model, wordpressEndpoint, mysqlEndpoint := s.wordpressModel()
289
wordpressEndpoint.SetUnitSettings("wordpress/0", map[string]interface{}{
292
wordpressEndpoint.SetUnitSettings("wordpress/1", map[string]interface{}{
295
mysqlEndpoint.SetUnitSettings("mysql/0", map[string]interface{}{
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")
307
func (s *ModelSerializationSuite) TestModelValidationChecksRelationsMissingSettings2(c *gc.C) {
308
model, wordpressEndpoint, _ := s.wordpressModel()
310
wordpressEndpoint.SetUnitSettings("wordpress/0", map[string]interface{}{
313
wordpressEndpoint.SetUnitSettings("wordpress/1", map[string]interface{}{
316
err := model.Validate()
317
c.Assert(err, gc.ErrorMatches, "missing relation settings for units \\[mysql/0\\] in relation 42")
320
func (s *ModelSerializationSuite) TestModelValidationChecksRelations(c *gc.C) {
321
model := s.wordpressModelWithSettings()
322
err := model.Validate()
323
c.Assert(err, jc.ErrorIsNil)
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)
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)
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"`)
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"`)
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 ""`)
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"`)
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`)
392
func (s *ModelSerializationSuite) TestModelValidationChecksAddressSubnetInvalid(c *gc.C) {
393
model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
394
args := IPAddressArgs{
397
Value: "192.168.1.1",
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"`)
407
func (s *ModelSerializationSuite) TestModelValidationChecksAddressSucceeds(c *gc.C) {
408
model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
409
args := IPAddressArgs{
412
Value: "192.168.1.1",
413
SubnetCIDR: "192.168.1.0/24",
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)
422
func (s *ModelSerializationSuite) TestModelValidationChecksAddressGatewayAddressInvalid(c *gc.C) {
423
model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
424
args := IPAddressArgs{
427
Value: "192.168.1.1",
428
SubnetCIDR: "192.168.1.0/24",
429
GatewayAddress: "foo",
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"`)
438
func (s *ModelSerializationSuite) TestModelValidationChecksAddressGatewayAddressValid(c *gc.C) {
439
model := NewModel(ModelArgs{Owner: names.NewUserTag("owner")})
440
args := IPAddressArgs{
443
Value: "192.168.1.2",
444
SubnetCIDR: "192.168.1.0/24",
445
GatewayAddress: "192.168.1.1",
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)
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)
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.*")
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"`)
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)
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`)
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`)
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"`)
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"`)
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)
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)
565
bytes, err := yaml.Marshal(initial)
566
c.Assert(err, jc.ErrorIsNil)
568
model, err := Deserialize(bytes)
569
c.Assert(err, jc.ErrorIsNil)
570
c.Assert(model.Spaces(), jc.DeepEquals, spaces)
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)
582
bytes, err := yaml.Marshal(initial)
583
c.Assert(err, jc.ErrorIsNil)
585
model, err := Deserialize(bytes)
586
c.Assert(err, jc.ErrorIsNil)
587
c.Assert(model.LinkLayerDevices(), jc.DeepEquals, devices)
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)
598
bytes, err := yaml.Marshal(initial)
599
c.Assert(err, jc.ErrorIsNil)
601
model, err := Deserialize(bytes)
602
c.Assert(err, jc.ErrorIsNil)
603
c.Assert(model.Subnets(), jc.DeepEquals, subnets)
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)
614
bytes, err := yaml.Marshal(initial)
615
c.Assert(err, jc.ErrorIsNil)
617
model, err := Deserialize(bytes)
618
c.Assert(err, jc.ErrorIsNil)
619
c.Assert(model.IPAddresses(), jc.DeepEquals, addresses)
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)
630
bytes, err := yaml.Marshal(initial)
631
c.Assert(err, jc.ErrorIsNil)
633
model, err := Deserialize(bytes)
634
c.Assert(err, jc.ErrorIsNil)
635
c.Assert(model.SSHHostKeys(), jc.DeepEquals, keys)
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`)
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)
653
bytes, err := yaml.Marshal(initial)
654
c.Assert(err, jc.ErrorIsNil)
656
model, err := Deserialize(bytes)
657
c.Assert(err, jc.ErrorIsNil)
658
c.Assert(model.Volumes(), jc.DeepEquals, volumes)
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`)
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)
677
bytes, err := yaml.Marshal(initial)
678
c.Assert(err, jc.ErrorIsNil)
680
model, err := Deserialize(bytes)
681
c.Assert(err, jc.ErrorIsNil)
682
c.Assert(model.Filesystems(), jc.DeepEquals, filesystems)