~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/testing/factory/factory.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 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package factory
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        "math/rand"
 
9
        "strconv"
 
10
        "sync/atomic"
 
11
        "time"
 
12
 
 
13
        jc "github.com/juju/testing/checkers"
 
14
        "github.com/juju/utils"
 
15
        "github.com/juju/utils/arch"
 
16
        "github.com/juju/utils/series"
 
17
        gc "gopkg.in/check.v1"
 
18
        "gopkg.in/juju/charm.v6-unstable"
 
19
        "gopkg.in/juju/names.v2"
 
20
 
 
21
        "github.com/juju/juju/constraints"
 
22
        "github.com/juju/juju/core/description"
 
23
        "github.com/juju/juju/instance"
 
24
        "github.com/juju/juju/network"
 
25
        "github.com/juju/juju/state"
 
26
        "github.com/juju/juju/status"
 
27
        "github.com/juju/juju/storage"
 
28
        "github.com/juju/juju/storage/provider"
 
29
        "github.com/juju/juju/testcharms"
 
30
        "github.com/juju/juju/testing"
 
31
        jujuversion "github.com/juju/juju/version"
 
32
        "github.com/juju/version"
 
33
)
 
34
 
 
35
const (
 
36
        symbols = "abcdefghijklmopqrstuvwxyz"
 
37
)
 
38
 
 
39
type Factory struct {
 
40
        st *state.State
 
41
}
 
42
 
 
43
var index uint32
 
44
 
 
45
func NewFactory(st *state.State) *Factory {
 
46
        return &Factory{st: st}
 
47
}
 
48
 
 
49
// UserParams defines the parameters for creating a user with MakeUser.
 
50
type UserParams struct {
 
51
        Name        string
 
52
        DisplayName string
 
53
        Password    string
 
54
        Creator     names.Tag
 
55
        NoModelUser bool
 
56
        Disabled    bool
 
57
        Access      description.Access
 
58
}
 
59
 
 
60
// ModelUserParams defines the parameters for creating an environment user.
 
61
type ModelUserParams struct {
 
62
        User        string
 
63
        DisplayName string
 
64
        CreatedBy   names.Tag
 
65
        Access      description.Access
 
66
}
 
67
 
 
68
// CharmParams defines the parameters for creating a charm.
 
69
type CharmParams struct {
 
70
        Name     string
 
71
        Series   string
 
72
        Revision string
 
73
        URL      string
 
74
}
 
75
 
 
76
// Params for creating a machine.
 
77
type MachineParams struct {
 
78
        Series          string
 
79
        Jobs            []state.MachineJob
 
80
        Password        string
 
81
        Nonce           string
 
82
        Constraints     constraints.Value
 
83
        InstanceId      instance.Id
 
84
        Characteristics *instance.HardwareCharacteristics
 
85
        Addresses       []network.Address
 
86
        Volumes         []state.MachineVolumeParams
 
87
        Filesystems     []state.MachineFilesystemParams
 
88
}
 
89
 
 
90
// ApplicationParams is used when specifying parameters for a new application.
 
91
type ApplicationParams struct {
 
92
        Name        string
 
93
        Charm       *state.Charm
 
94
        Status      *status.StatusInfo
 
95
        Settings    map[string]interface{}
 
96
        Storage     map[string]state.StorageConstraints
 
97
        Constraints constraints.Value
 
98
}
 
99
 
 
100
// UnitParams are used to create units.
 
101
type UnitParams struct {
 
102
        Application *state.Application
 
103
        Machine     *state.Machine
 
104
        Password    string
 
105
        SetCharmURL bool
 
106
        Status      *status.StatusInfo
 
107
        Constraints constraints.Value
 
108
}
 
109
 
 
110
// RelationParams are used to create relations.
 
111
type RelationParams struct {
 
112
        Endpoints []state.Endpoint
 
113
}
 
114
 
 
115
type MetricParams struct {
 
116
        Unit       *state.Unit
 
117
        Time       *time.Time
 
118
        Metrics    []state.Metric
 
119
        Sent       bool
 
120
        DeleteTime *time.Time
 
121
}
 
122
 
 
123
type ModelParams struct {
 
124
        Name                    string
 
125
        Owner                   names.Tag
 
126
        ConfigAttrs             testing.Attrs
 
127
        CloudName               string
 
128
        CloudRegion             string
 
129
        CloudCredential         string
 
130
        StorageProviderRegistry storage.ProviderRegistry
 
131
}
 
132
 
 
133
type SpaceParams struct {
 
134
        Name       string
 
135
        ProviderID network.Id
 
136
        Subnets    []string
 
137
        IsPublic   bool
 
138
}
 
139
 
 
140
// RandomSuffix adds a random 5 character suffix to the presented string.
 
141
func (*Factory) RandomSuffix(prefix string) string {
 
142
        result := prefix
 
143
        for i := 0; i < 5; i++ {
 
144
                result += string(symbols[rand.Intn(len(symbols))])
 
145
        }
 
146
        return result
 
147
}
 
148
 
 
149
func uniqueInteger() int {
 
150
        return int(atomic.AddUint32(&index, 1))
 
151
}
 
152
 
 
153
func uniqueString(prefix string) string {
 
154
        if prefix == "" {
 
155
                prefix = "no-prefix"
 
156
        }
 
157
        return fmt.Sprintf("%s-%d", prefix, uniqueInteger())
 
158
}
 
159
 
 
160
// MakeUser will create a user with values defined by the params.
 
161
// For attributes of UserParams that are the default empty values,
 
162
// some meaningful valid values are used instead.
 
163
// If params is not specified, defaults are used.
 
164
// If params.NoModelUser is false, the user will also be created
 
165
// in the current model.
 
166
func (factory *Factory) MakeUser(c *gc.C, params *UserParams) *state.User {
 
167
        if params == nil {
 
168
                params = &UserParams{}
 
169
        }
 
170
        if params.Name == "" {
 
171
                params.Name = uniqueString("username")
 
172
        }
 
173
        if params.DisplayName == "" {
 
174
                params.DisplayName = uniqueString("display name")
 
175
        }
 
176
        if params.Password == "" {
 
177
                params.Password = "password"
 
178
        }
 
179
        if params.Creator == nil {
 
180
                env, err := factory.st.Model()
 
181
                c.Assert(err, jc.ErrorIsNil)
 
182
                params.Creator = env.Owner()
 
183
        }
 
184
        if params.Access == description.UndefinedAccess {
 
185
                params.Access = description.AdminAccess
 
186
        }
 
187
        creatorUserTag := params.Creator.(names.UserTag)
 
188
        user, err := factory.st.AddUser(
 
189
                params.Name, params.DisplayName, params.Password, creatorUserTag.Name())
 
190
        c.Assert(err, jc.ErrorIsNil)
 
191
        if !params.NoModelUser {
 
192
                _, err := factory.st.AddModelUser(state.UserAccessSpec{
 
193
                        User:        user.UserTag(),
 
194
                        CreatedBy:   names.NewUserTag(user.CreatedBy()),
 
195
                        DisplayName: params.DisplayName,
 
196
                        Access:      params.Access,
 
197
                })
 
198
                c.Assert(err, jc.ErrorIsNil)
 
199
        }
 
200
        if params.Disabled {
 
201
                err := user.Disable()
 
202
                c.Assert(err, jc.ErrorIsNil)
 
203
        }
 
204
        return user
 
205
}
 
206
 
 
207
// MakeModelUser will create a modelUser with values defined by the params. For
 
208
// attributes of ModelUserParams that are the default empty values, some
 
209
// meaningful valid values are used instead. If params is not specified,
 
210
// defaults are used.
 
211
func (factory *Factory) MakeModelUser(c *gc.C, params *ModelUserParams) description.UserAccess {
 
212
        if params == nil {
 
213
                params = &ModelUserParams{}
 
214
        }
 
215
        if params.User == "" {
 
216
                user := factory.MakeUser(c, &UserParams{NoModelUser: true})
 
217
                params.User = user.UserTag().Canonical()
 
218
        }
 
219
        if params.DisplayName == "" {
 
220
                params.DisplayName = uniqueString("display name")
 
221
        }
 
222
        if params.Access == description.UndefinedAccess {
 
223
                params.Access = description.AdminAccess
 
224
        }
 
225
        if params.CreatedBy == nil {
 
226
                env, err := factory.st.Model()
 
227
                c.Assert(err, jc.ErrorIsNil)
 
228
                params.CreatedBy = env.Owner()
 
229
        }
 
230
        createdByUserTag := params.CreatedBy.(names.UserTag)
 
231
        modelUser, err := factory.st.AddModelUser(state.UserAccessSpec{
 
232
                User:        names.NewUserTag(params.User),
 
233
                CreatedBy:   createdByUserTag,
 
234
                DisplayName: params.DisplayName,
 
235
                Access:      params.Access,
 
236
        })
 
237
        c.Assert(err, jc.ErrorIsNil)
 
238
        return modelUser
 
239
}
 
240
 
 
241
func (factory *Factory) paramsFillDefaults(c *gc.C, params *MachineParams) *MachineParams {
 
242
        if params == nil {
 
243
                params = &MachineParams{}
 
244
        }
 
245
        if params.Series == "" {
 
246
                params.Series = "quantal"
 
247
        }
 
248
        if params.Nonce == "" {
 
249
                params.Nonce = "nonce"
 
250
        }
 
251
        if len(params.Jobs) == 0 {
 
252
                params.Jobs = []state.MachineJob{state.JobHostUnits}
 
253
        }
 
254
        if params.InstanceId == "" {
 
255
                params.InstanceId = instance.Id(uniqueString("id"))
 
256
        }
 
257
        if params.Password == "" {
 
258
                var err error
 
259
                params.Password, err = utils.RandomPassword()
 
260
                c.Assert(err, jc.ErrorIsNil)
 
261
        }
 
262
        if params.Characteristics == nil {
 
263
                arch := "amd64"
 
264
                mem := uint64(64 * 1024 * 1024 * 1024)
 
265
                hardware := instance.HardwareCharacteristics{
 
266
                        Arch: &arch,
 
267
                        Mem:  &mem,
 
268
                }
 
269
                params.Characteristics = &hardware
 
270
        }
 
271
 
 
272
        return params
 
273
}
 
274
 
 
275
// MakeMachineNested will make a machine nested in the machine with ID given.
 
276
func (factory *Factory) MakeMachineNested(c *gc.C, parentId string, params *MachineParams) *state.Machine {
 
277
        params = factory.paramsFillDefaults(c, params)
 
278
        machineTemplate := state.MachineTemplate{
 
279
                Series:      params.Series,
 
280
                Jobs:        params.Jobs,
 
281
                Volumes:     params.Volumes,
 
282
                Filesystems: params.Filesystems,
 
283
                Constraints: params.Constraints,
 
284
        }
 
285
 
 
286
        m, err := factory.st.AddMachineInsideMachine(
 
287
                machineTemplate,
 
288
                parentId,
 
289
                instance.LXD,
 
290
        )
 
291
        c.Assert(err, jc.ErrorIsNil)
 
292
        err = m.SetProvisioned(params.InstanceId, params.Nonce, params.Characteristics)
 
293
        c.Assert(err, jc.ErrorIsNil)
 
294
        current := version.Binary{
 
295
                Number: jujuversion.Current,
 
296
                Arch:   arch.HostArch(),
 
297
                Series: series.HostSeries(),
 
298
        }
 
299
        err = m.SetAgentVersion(current)
 
300
        c.Assert(err, jc.ErrorIsNil)
 
301
        return m
 
302
}
 
303
 
 
304
// MakeMachine will add a machine with values defined in params. For some
 
305
// values in params, if they are missing, some meaningful empty values will be
 
306
// set.
 
307
// If params is not specified, defaults are used.
 
308
func (factory *Factory) MakeMachine(c *gc.C, params *MachineParams) *state.Machine {
 
309
        machine, _ := factory.MakeMachineReturningPassword(c, params)
 
310
        return machine
 
311
}
 
312
 
 
313
// MakeMachineReturningPassword will add a machine with values defined in
 
314
// params. For some values in params, if they are missing, some meaningful
 
315
// empty values will be set. If params is not specified, defaults are used.
 
316
// The machine and its password are returned.
 
317
func (factory *Factory) MakeMachineReturningPassword(c *gc.C, params *MachineParams) (*state.Machine, string) {
 
318
        params = factory.paramsFillDefaults(c, params)
 
319
        machineTemplate := state.MachineTemplate{
 
320
                Series:      params.Series,
 
321
                Jobs:        params.Jobs,
 
322
                Volumes:     params.Volumes,
 
323
                Filesystems: params.Filesystems,
 
324
                Constraints: params.Constraints,
 
325
        }
 
326
        machine, err := factory.st.AddOneMachine(machineTemplate)
 
327
        c.Assert(err, jc.ErrorIsNil)
 
328
        err = machine.SetProvisioned(params.InstanceId, params.Nonce, params.Characteristics)
 
329
        c.Assert(err, jc.ErrorIsNil)
 
330
        err = machine.SetPassword(params.Password)
 
331
        c.Assert(err, jc.ErrorIsNil)
 
332
        if len(params.Addresses) > 0 {
 
333
                err := machine.SetProviderAddresses(params.Addresses...)
 
334
                c.Assert(err, jc.ErrorIsNil)
 
335
        }
 
336
        current := version.Binary{
 
337
                Number: jujuversion.Current,
 
338
                Arch:   arch.HostArch(),
 
339
                Series: series.HostSeries(),
 
340
        }
 
341
        err = machine.SetAgentVersion(current)
 
342
        c.Assert(err, jc.ErrorIsNil)
 
343
        return machine, params.Password
 
344
}
 
345
 
 
346
// MakeCharm creates a charm with the values specified in params.
 
347
// Sensible default values are substituted for missing ones.
 
348
// Supported charms depend on the charm/testing package.
 
349
// Currently supported charms:
 
350
//   all-hooks, category, dummy, format2, logging, monitoring, mysql,
 
351
//   mysql-alternative, riak, terracotta, upgrade1, upgrade2, varnish,
 
352
//   varnish-alternative, wordpress.
 
353
// If params is not specified, defaults are used.
 
354
func (factory *Factory) MakeCharm(c *gc.C, params *CharmParams) *state.Charm {
 
355
        if params == nil {
 
356
                params = &CharmParams{}
 
357
        }
 
358
        if params.Name == "" {
 
359
                params.Name = "mysql"
 
360
        }
 
361
        if params.Series == "" {
 
362
                params.Series = "quantal"
 
363
        }
 
364
        if params.Revision == "" {
 
365
                params.Revision = fmt.Sprintf("%d", uniqueInteger())
 
366
        }
 
367
        if params.URL == "" {
 
368
                params.URL = fmt.Sprintf("cs:%s/%s-%s", params.Series, params.Name, params.Revision)
 
369
        }
 
370
 
 
371
        ch := testcharms.Repo.CharmDir(params.Name)
 
372
 
 
373
        curl := charm.MustParseURL(params.URL)
 
374
        bundleSHA256 := uniqueString("bundlesha")
 
375
        info := state.CharmInfo{
 
376
                Charm:       ch,
 
377
                ID:          curl,
 
378
                StoragePath: "fake-storage-path",
 
379
                SHA256:      bundleSHA256,
 
380
        }
 
381
        charm, err := factory.st.AddCharm(info)
 
382
        c.Assert(err, jc.ErrorIsNil)
 
383
        return charm
 
384
}
 
385
 
 
386
// MakeApplication creates an application with the specified parameters, substituting
 
387
// sane defaults for missing values.
 
388
// If params is not specified, defaults are used.
 
389
func (factory *Factory) MakeApplication(c *gc.C, params *ApplicationParams) *state.Application {
 
390
        if params == nil {
 
391
                params = &ApplicationParams{}
 
392
        }
 
393
        if params.Charm == nil {
 
394
                params.Charm = factory.MakeCharm(c, nil)
 
395
        }
 
396
        if params.Name == "" {
 
397
                params.Name = params.Charm.Meta().Name
 
398
        }
 
399
        application, err := factory.st.AddApplication(state.AddApplicationArgs{
 
400
                Name:        params.Name,
 
401
                Charm:       params.Charm,
 
402
                Settings:    charm.Settings(params.Settings),
 
403
                Storage:     params.Storage,
 
404
                Constraints: params.Constraints,
 
405
        })
 
406
        c.Assert(err, jc.ErrorIsNil)
 
407
 
 
408
        if params.Status != nil {
 
409
                now := time.Now()
 
410
                s := status.StatusInfo{
 
411
                        Status:  params.Status.Status,
 
412
                        Message: params.Status.Message,
 
413
                        Data:    params.Status.Data,
 
414
                        Since:   &now,
 
415
                }
 
416
                err = application.SetStatus(s)
 
417
                c.Assert(err, jc.ErrorIsNil)
 
418
        }
 
419
 
 
420
        return application
 
421
}
 
422
 
 
423
// MakeUnit creates an application unit with specified params, filling in
 
424
// sane defaults for missing values.
 
425
// If params is not specified, defaults are used.
 
426
func (factory *Factory) MakeUnit(c *gc.C, params *UnitParams) *state.Unit {
 
427
        unit, _ := factory.MakeUnitReturningPassword(c, params)
 
428
        return unit
 
429
}
 
430
 
 
431
// MakeUnit creates an application unit with specified params, filling in sane
 
432
// defaults for missing values. If params is not specified, defaults are used.
 
433
// The unit and its password are returned.
 
434
func (factory *Factory) MakeUnitReturningPassword(c *gc.C, params *UnitParams) (*state.Unit, string) {
 
435
        if params == nil {
 
436
                params = &UnitParams{}
 
437
        }
 
438
        if params.Machine == nil {
 
439
                params.Machine = factory.MakeMachine(c, nil)
 
440
        }
 
441
        if params.Application == nil {
 
442
                params.Application = factory.MakeApplication(c, &ApplicationParams{
 
443
                        Constraints: params.Constraints,
 
444
                })
 
445
        }
 
446
        if params.Password == "" {
 
447
                var err error
 
448
                params.Password, err = utils.RandomPassword()
 
449
                c.Assert(err, jc.ErrorIsNil)
 
450
        }
 
451
        unit, err := params.Application.AddUnit()
 
452
        c.Assert(err, jc.ErrorIsNil)
 
453
        err = unit.AssignToMachine(params.Machine)
 
454
        c.Assert(err, jc.ErrorIsNil)
 
455
 
 
456
        agentTools := version.Binary{
 
457
                Number: jujuversion.Current,
 
458
                Arch:   arch.HostArch(),
 
459
                Series: params.Application.Series(),
 
460
        }
 
461
        err = unit.SetAgentVersion(agentTools)
 
462
        c.Assert(err, jc.ErrorIsNil)
 
463
        if params.SetCharmURL {
 
464
                applicationCharmURL, _ := params.Application.CharmURL()
 
465
                err = unit.SetCharmURL(applicationCharmURL)
 
466
                c.Assert(err, jc.ErrorIsNil)
 
467
        }
 
468
        err = unit.SetPassword(params.Password)
 
469
        c.Assert(err, jc.ErrorIsNil)
 
470
 
 
471
        if params.Status != nil {
 
472
                now := time.Now()
 
473
                s := status.StatusInfo{
 
474
                        Status:  params.Status.Status,
 
475
                        Message: params.Status.Message,
 
476
                        Data:    params.Status.Data,
 
477
                        Since:   &now,
 
478
                }
 
479
                err = unit.SetStatus(s)
 
480
                c.Assert(err, jc.ErrorIsNil)
 
481
        }
 
482
 
 
483
        return unit, params.Password
 
484
}
 
485
 
 
486
// MakeMetric makes a metric with specified params, filling in
 
487
// sane defaults for missing values.
 
488
// If params is not specified, defaults are used.
 
489
func (factory *Factory) MakeMetric(c *gc.C, params *MetricParams) *state.MetricBatch {
 
490
        now := time.Now().Round(time.Second).UTC()
 
491
        if params == nil {
 
492
                params = &MetricParams{}
 
493
        }
 
494
        if params.Unit == nil {
 
495
                meteredCharm := factory.MakeCharm(c, &CharmParams{Name: "metered", URL: "cs:quantal/metered"})
 
496
                meteredApplication := factory.MakeApplication(c, &ApplicationParams{Charm: meteredCharm})
 
497
                params.Unit = factory.MakeUnit(c, &UnitParams{Application: meteredApplication, SetCharmURL: true})
 
498
        }
 
499
        if params.Time == nil {
 
500
                params.Time = &now
 
501
        }
 
502
        if params.Metrics == nil {
 
503
                params.Metrics = []state.Metric{{"pings", strconv.Itoa(uniqueInteger()), *params.Time}}
 
504
        }
 
505
 
 
506
        chURL, ok := params.Unit.CharmURL()
 
507
        c.Assert(ok, gc.Equals, true)
 
508
 
 
509
        metric, err := factory.st.AddMetrics(
 
510
                state.BatchParam{
 
511
                        UUID:     utils.MustNewUUID().String(),
 
512
                        Created:  *params.Time,
 
513
                        CharmURL: chURL.String(),
 
514
                        Metrics:  params.Metrics,
 
515
                        Unit:     params.Unit.UnitTag(),
 
516
                })
 
517
        c.Assert(err, jc.ErrorIsNil)
 
518
        if params.Sent {
 
519
                t := now
 
520
                if params.DeleteTime != nil {
 
521
                        t = *params.DeleteTime
 
522
                }
 
523
                err := metric.SetSent(t)
 
524
                c.Assert(err, jc.ErrorIsNil)
 
525
        }
 
526
        return metric
 
527
}
 
528
 
 
529
// MakeRelation create a relation with specified params, filling in sane
 
530
// defaults for missing values.
 
531
// If params is not specified, defaults are used.
 
532
func (factory *Factory) MakeRelation(c *gc.C, params *RelationParams) *state.Relation {
 
533
        if params == nil {
 
534
                params = &RelationParams{}
 
535
        }
 
536
        if len(params.Endpoints) == 0 {
 
537
                s1 := factory.MakeApplication(c, &ApplicationParams{
 
538
                        Charm: factory.MakeCharm(c, &CharmParams{
 
539
                                Name: "mysql",
 
540
                        }),
 
541
                })
 
542
                e1, err := s1.Endpoint("server")
 
543
                c.Assert(err, jc.ErrorIsNil)
 
544
 
 
545
                s2 := factory.MakeApplication(c, &ApplicationParams{
 
546
                        Charm: factory.MakeCharm(c, &CharmParams{
 
547
                                Name: "wordpress",
 
548
                        }),
 
549
                })
 
550
                e2, err := s2.Endpoint("db")
 
551
                c.Assert(err, jc.ErrorIsNil)
 
552
 
 
553
                params.Endpoints = []state.Endpoint{e1, e2}
 
554
        }
 
555
 
 
556
        relation, err := factory.st.AddRelation(params.Endpoints...)
 
557
        c.Assert(err, jc.ErrorIsNil)
 
558
 
 
559
        return relation
 
560
}
 
561
 
 
562
// MakeModel creates an model with specified params,
 
563
// filling in sane defaults for missing values. If params is nil,
 
564
// defaults are used for all values.
 
565
//
 
566
// By default the new model shares the same owner as the calling
 
567
// Factory's model.
 
568
func (factory *Factory) MakeModel(c *gc.C, params *ModelParams) *state.State {
 
569
        if params == nil {
 
570
                params = new(ModelParams)
 
571
        }
 
572
        if params.Name == "" {
 
573
                params.Name = uniqueString("testenv")
 
574
        }
 
575
        if params.CloudName == "" {
 
576
                params.CloudName = "dummy"
 
577
        }
 
578
        if params.Owner == nil {
 
579
                origEnv, err := factory.st.Model()
 
580
                c.Assert(err, jc.ErrorIsNil)
 
581
                params.Owner = origEnv.Owner()
 
582
        }
 
583
        if params.StorageProviderRegistry == nil {
 
584
                params.StorageProviderRegistry = provider.CommonStorageProviders()
 
585
        }
 
586
        // It only makes sense to make an model with the same provider
 
587
        // as the initial model, or things will break elsewhere.
 
588
        currentCfg, err := factory.st.ModelConfig()
 
589
        c.Assert(err, jc.ErrorIsNil)
 
590
 
 
591
        uuid, err := utils.NewUUID()
 
592
        c.Assert(err, jc.ErrorIsNil)
 
593
        cfg := testing.CustomModelConfig(c, testing.Attrs{
 
594
                "name": params.Name,
 
595
                "uuid": uuid.String(),
 
596
                "type": currentCfg.Type(),
 
597
        }.Merge(params.ConfigAttrs))
 
598
        _, st, err := factory.st.NewModel(state.ModelArgs{
 
599
                CloudName:       params.CloudName,
 
600
                CloudRegion:     params.CloudRegion,
 
601
                CloudCredential: params.CloudCredential,
 
602
                Config:          cfg,
 
603
                Owner:           params.Owner.(names.UserTag),
 
604
                StorageProviderRegistry: params.StorageProviderRegistry,
 
605
        })
 
606
        c.Assert(err, jc.ErrorIsNil)
 
607
        return st
 
608
}
 
609
 
 
610
// MakeSpace will create a new space with the specified params. If the space
 
611
// name is not set, a unique space name is created.
 
612
func (factory *Factory) MakeSpace(c *gc.C, params *SpaceParams) *state.Space {
 
613
        if params == nil {
 
614
                params = new(SpaceParams)
 
615
        }
 
616
        if params.Name == "" {
 
617
                params.Name = uniqueString("space-")
 
618
        }
 
619
        space, err := factory.st.AddSpace(params.Name, params.ProviderID, params.Subnets, params.IsPublic)
 
620
        c.Assert(err, jc.ErrorIsNil)
 
621
        return space
 
622
}