~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/juju/deploy_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 2012, 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package juju_test
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        stdtesting "testing"
 
9
 
 
10
        "github.com/juju/errors"
 
11
        jc "github.com/juju/testing/checkers"
 
12
        "github.com/juju/utils/set"
 
13
        gc "gopkg.in/check.v1"
 
14
        "gopkg.in/juju/charm.v6-unstable"
 
15
        "gopkg.in/juju/charmrepo.v2-unstable"
 
16
 
 
17
        "github.com/juju/juju/constraints"
 
18
        "github.com/juju/juju/instance"
 
19
        "github.com/juju/juju/juju"
 
20
        "github.com/juju/juju/juju/testing"
 
21
        "github.com/juju/juju/state"
 
22
        "github.com/juju/juju/testcharms"
 
23
        coretesting "github.com/juju/juju/testing"
 
24
)
 
25
 
 
26
func Test(t *stdtesting.T) {
 
27
        coretesting.MgoTestPackage(t)
 
28
}
 
29
 
 
30
// DeployLocalSuite uses a fresh copy of the same local dummy charm for each
 
31
// test, because DeployApplication demands that a charm already exists in state,
 
32
// and that's is the simplest way to get one in there.
 
33
type DeployLocalSuite struct {
 
34
        testing.JujuConnSuite
 
35
        repo        charmrepo.Interface
 
36
        charm       *state.Charm
 
37
        oldCacheDir string
 
38
}
 
39
 
 
40
var _ = gc.Suite(&DeployLocalSuite{})
 
41
 
 
42
func (s *DeployLocalSuite) SetUpSuite(c *gc.C) {
 
43
        s.JujuConnSuite.SetUpSuite(c)
 
44
        s.repo = &charmrepo.LocalRepository{Path: testcharms.Repo.Path()}
 
45
        s.PatchValue(&charmrepo.CacheDir, c.MkDir())
 
46
}
 
47
 
 
48
func (s *DeployLocalSuite) SetUpTest(c *gc.C) {
 
49
        s.JujuConnSuite.SetUpTest(c)
 
50
        curl := charm.MustParseURL("local:quantal/dummy")
 
51
        charm, err := testing.PutCharm(s.State, curl, s.repo, false)
 
52
        c.Assert(err, jc.ErrorIsNil)
 
53
        s.charm = charm
 
54
}
 
55
 
 
56
func (s *DeployLocalSuite) TestDeployMinimal(c *gc.C) {
 
57
        service, err := juju.DeployApplication(s.State,
 
58
                juju.DeployApplicationParams{
 
59
                        ApplicationName: "bob",
 
60
                        Charm:           s.charm,
 
61
                })
 
62
        c.Assert(err, jc.ErrorIsNil)
 
63
        s.assertCharm(c, service, s.charm.URL())
 
64
        s.assertSettings(c, service, charm.Settings{})
 
65
        s.assertConstraints(c, service, constraints.Value{})
 
66
        s.assertMachines(c, service, constraints.Value{})
 
67
}
 
68
 
 
69
func (s *DeployLocalSuite) TestDeploySeries(c *gc.C) {
 
70
        f := &fakeDeployer{State: s.State}
 
71
 
 
72
        _, err := juju.DeployApplication(f,
 
73
                juju.DeployApplicationParams{
 
74
                        ApplicationName: "bob",
 
75
                        Charm:           s.charm,
 
76
                        Series:          "aseries",
 
77
                })
 
78
        c.Assert(err, jc.ErrorIsNil)
 
79
 
 
80
        c.Assert(f.args.Name, gc.Equals, "bob")
 
81
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
82
        c.Assert(f.args.Series, gc.Equals, "aseries")
 
83
}
 
84
 
 
85
func (s *DeployLocalSuite) TestDeployWithImplicitBindings(c *gc.C) {
 
86
        wordpressCharm := s.addWordpressCharmWithExtraBindings(c)
 
87
 
 
88
        service, err := juju.DeployApplication(s.State,
 
89
                juju.DeployApplicationParams{
 
90
                        ApplicationName:  "bob",
 
91
                        Charm:            wordpressCharm,
 
92
                        EndpointBindings: nil,
 
93
                })
 
94
        c.Assert(err, jc.ErrorIsNil)
 
95
 
 
96
        s.assertBindings(c, service, map[string]string{
 
97
                // relation names
 
98
                "url":             "",
 
99
                "logging-dir":     "",
 
100
                "monitoring-port": "",
 
101
                "db":              "",
 
102
                "cache":           "",
 
103
                "cluster":         "",
 
104
                // extra-bindings names
 
105
                "db-client": "",
 
106
                "admin-api": "",
 
107
                "foo-bar":   "",
 
108
        })
 
109
}
 
110
 
 
111
func (s *DeployLocalSuite) addWordpressCharm(c *gc.C) *state.Charm {
 
112
        wordpressCharmURL := charm.MustParseURL("local:quantal/wordpress")
 
113
        return s.addWordpressCharmFromURL(c, wordpressCharmURL)
 
114
}
 
115
 
 
116
func (s *DeployLocalSuite) addWordpressCharmWithExtraBindings(c *gc.C) *state.Charm {
 
117
        wordpressCharmURL := charm.MustParseURL("local:quantal/wordpress-extra-bindings")
 
118
        return s.addWordpressCharmFromURL(c, wordpressCharmURL)
 
119
}
 
120
 
 
121
func (s *DeployLocalSuite) addWordpressCharmFromURL(c *gc.C, charmURL *charm.URL) *state.Charm {
 
122
        wordpressCharm, err := testing.PutCharm(s.State, charmURL, s.repo, false)
 
123
        c.Assert(err, jc.ErrorIsNil)
 
124
        return wordpressCharm
 
125
}
 
126
 
 
127
func (s *DeployLocalSuite) assertBindings(c *gc.C, service *state.Application, expected map[string]string) {
 
128
        bindings, err := service.EndpointBindings()
 
129
        c.Assert(err, jc.ErrorIsNil)
 
130
        c.Assert(bindings, jc.DeepEquals, expected)
 
131
}
 
132
 
 
133
func (s *DeployLocalSuite) TestDeployWithSomeSpecifiedBindings(c *gc.C) {
 
134
        wordpressCharm := s.addWordpressCharm(c)
 
135
        _, err := s.State.AddSpace("db", "", nil, false)
 
136
        c.Assert(err, jc.ErrorIsNil)
 
137
        _, err = s.State.AddSpace("public", "", nil, false)
 
138
        c.Assert(err, jc.ErrorIsNil)
 
139
 
 
140
        service, err := juju.DeployApplication(s.State,
 
141
                juju.DeployApplicationParams{
 
142
                        ApplicationName: "bob",
 
143
                        Charm:           wordpressCharm,
 
144
                        EndpointBindings: map[string]string{
 
145
                                "":   "public",
 
146
                                "db": "db",
 
147
                        },
 
148
                })
 
149
        c.Assert(err, jc.ErrorIsNil)
 
150
 
 
151
        s.assertBindings(c, service, map[string]string{
 
152
                // relation names
 
153
                "url":             "public",
 
154
                "logging-dir":     "public",
 
155
                "monitoring-port": "public",
 
156
                "db":              "db",
 
157
                "cache":           "public",
 
158
                // extra-bindings names
 
159
                "db-client": "public",
 
160
                "admin-api": "public",
 
161
                "foo-bar":   "public",
 
162
        })
 
163
}
 
164
 
 
165
func (s *DeployLocalSuite) TestDeployWithBoundRelationNamesAndExtraBindingsNames(c *gc.C) {
 
166
        wordpressCharm := s.addWordpressCharmWithExtraBindings(c)
 
167
        _, err := s.State.AddSpace("db", "", nil, false)
 
168
        c.Assert(err, jc.ErrorIsNil)
 
169
        _, err = s.State.AddSpace("public", "", nil, false)
 
170
        c.Assert(err, jc.ErrorIsNil)
 
171
        _, err = s.State.AddSpace("internal", "", nil, false)
 
172
        c.Assert(err, jc.ErrorIsNil)
 
173
 
 
174
        service, err := juju.DeployApplication(s.State,
 
175
                juju.DeployApplicationParams{
 
176
                        ApplicationName: "bob",
 
177
                        Charm:           wordpressCharm,
 
178
                        EndpointBindings: map[string]string{
 
179
                                "":          "public",
 
180
                                "db":        "db",
 
181
                                "db-client": "db",
 
182
                                "admin-api": "internal",
 
183
                        },
 
184
                })
 
185
        c.Assert(err, jc.ErrorIsNil)
 
186
 
 
187
        s.assertBindings(c, service, map[string]string{
 
188
                "url":             "public",
 
189
                "logging-dir":     "public",
 
190
                "monitoring-port": "public",
 
191
                "db":              "db",
 
192
                "cache":           "public",
 
193
                "db-client":       "db",
 
194
                "admin-api":       "internal",
 
195
                "cluster":         "public",
 
196
                "foo-bar":         "public", // like for relations, uses the application-default.
 
197
        })
 
198
}
 
199
 
 
200
func (s *DeployLocalSuite) TestDeployResources(c *gc.C) {
 
201
        f := &fakeDeployer{State: s.State}
 
202
 
 
203
        _, err := juju.DeployApplication(f,
 
204
                juju.DeployApplicationParams{
 
205
                        ApplicationName: "bob",
 
206
                        Charm:           s.charm,
 
207
                        EndpointBindings: map[string]string{
 
208
                                "":   "public",
 
209
                                "db": "db",
 
210
                        },
 
211
                        Resources: map[string]string{"foo": "bar"},
 
212
                })
 
213
        c.Assert(err, jc.ErrorIsNil)
 
214
 
 
215
        c.Assert(f.args.Name, gc.Equals, "bob")
 
216
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
217
        c.Assert(f.args.Resources, gc.DeepEquals, map[string]string{"foo": "bar"})
 
218
}
 
219
 
 
220
func (s *DeployLocalSuite) TestDeploySettings(c *gc.C) {
 
221
        service, err := juju.DeployApplication(s.State,
 
222
                juju.DeployApplicationParams{
 
223
                        ApplicationName: "bob",
 
224
                        Charm:           s.charm,
 
225
                        ConfigSettings: charm.Settings{
 
226
                                "title":       "banana cupcakes",
 
227
                                "skill-level": 9901,
 
228
                        },
 
229
                })
 
230
        c.Assert(err, jc.ErrorIsNil)
 
231
        s.assertSettings(c, service, charm.Settings{
 
232
                "title":       "banana cupcakes",
 
233
                "skill-level": int64(9901),
 
234
        })
 
235
}
 
236
 
 
237
func (s *DeployLocalSuite) TestDeploySettingsError(c *gc.C) {
 
238
        _, err := juju.DeployApplication(s.State,
 
239
                juju.DeployApplicationParams{
 
240
                        ApplicationName: "bob",
 
241
                        Charm:           s.charm,
 
242
                        ConfigSettings: charm.Settings{
 
243
                                "skill-level": 99.01,
 
244
                        },
 
245
                })
 
246
        c.Assert(err, gc.ErrorMatches, `option "skill-level" expected int, got 99.01`)
 
247
        _, err = s.State.Application("bob")
 
248
        c.Assert(err, jc.Satisfies, errors.IsNotFound)
 
249
}
 
250
 
 
251
func (s *DeployLocalSuite) TestDeployConstraints(c *gc.C) {
 
252
        err := s.State.SetModelConstraints(constraints.MustParse("mem=2G"))
 
253
        c.Assert(err, jc.ErrorIsNil)
 
254
        serviceCons := constraints.MustParse("cpu-cores=2")
 
255
        service, err := juju.DeployApplication(s.State,
 
256
                juju.DeployApplicationParams{
 
257
                        ApplicationName: "bob",
 
258
                        Charm:           s.charm,
 
259
                        Constraints:     serviceCons,
 
260
                })
 
261
        c.Assert(err, jc.ErrorIsNil)
 
262
        s.assertConstraints(c, service, serviceCons)
 
263
}
 
264
 
 
265
func (s *DeployLocalSuite) TestDeployNumUnits(c *gc.C) {
 
266
        f := &fakeDeployer{State: s.State}
 
267
 
 
268
        serviceCons := constraints.MustParse("cpu-cores=2")
 
269
        _, err := juju.DeployApplication(f,
 
270
                juju.DeployApplicationParams{
 
271
                        ApplicationName: "bob",
 
272
                        Charm:           s.charm,
 
273
                        Constraints:     serviceCons,
 
274
                        NumUnits:        2,
 
275
                })
 
276
        c.Assert(err, jc.ErrorIsNil)
 
277
 
 
278
        c.Assert(f.args.Name, gc.Equals, "bob")
 
279
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
280
        c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
 
281
        c.Assert(f.args.NumUnits, gc.Equals, 2)
 
282
}
 
283
 
 
284
func (s *DeployLocalSuite) TestDeployForceMachineId(c *gc.C) {
 
285
        f := &fakeDeployer{State: s.State}
 
286
 
 
287
        serviceCons := constraints.MustParse("cpu-cores=2")
 
288
        _, err := juju.DeployApplication(f,
 
289
                juju.DeployApplicationParams{
 
290
                        ApplicationName: "bob",
 
291
                        Charm:           s.charm,
 
292
                        Constraints:     serviceCons,
 
293
                        NumUnits:        1,
 
294
                        Placement:       []*instance.Placement{instance.MustParsePlacement("0")},
 
295
                })
 
296
        c.Assert(err, jc.ErrorIsNil)
 
297
 
 
298
        c.Assert(f.args.Name, gc.Equals, "bob")
 
299
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
300
        c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
 
301
        c.Assert(f.args.NumUnits, gc.Equals, 1)
 
302
        c.Assert(f.args.Placement, gc.HasLen, 1)
 
303
        c.Assert(*f.args.Placement[0], gc.Equals, instance.Placement{Scope: instance.MachineScope, Directive: "0"})
 
304
}
 
305
 
 
306
func (s *DeployLocalSuite) TestDeployForceMachineIdWithContainer(c *gc.C) {
 
307
        f := &fakeDeployer{State: s.State}
 
308
 
 
309
        serviceCons := constraints.MustParse("cpu-cores=2")
 
310
        _, err := juju.DeployApplication(f,
 
311
                juju.DeployApplicationParams{
 
312
                        ApplicationName: "bob",
 
313
                        Charm:           s.charm,
 
314
                        Constraints:     serviceCons,
 
315
                        NumUnits:        1,
 
316
                        Placement:       []*instance.Placement{instance.MustParsePlacement(fmt.Sprintf("%s:0", instance.LXD))},
 
317
                })
 
318
        c.Assert(err, jc.ErrorIsNil)
 
319
        c.Assert(f.args.Name, gc.Equals, "bob")
 
320
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
321
        c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
 
322
        c.Assert(f.args.NumUnits, gc.Equals, 1)
 
323
        c.Assert(f.args.Placement, gc.HasLen, 1)
 
324
        c.Assert(*f.args.Placement[0], gc.Equals, instance.Placement{Scope: string(instance.LXD), Directive: "0"})
 
325
}
 
326
 
 
327
func (s *DeployLocalSuite) TestDeploy(c *gc.C) {
 
328
        f := &fakeDeployer{State: s.State}
 
329
 
 
330
        serviceCons := constraints.MustParse("cpu-cores=2")
 
331
        placement := []*instance.Placement{
 
332
                {Scope: s.State.ModelUUID(), Directive: "valid"},
 
333
                {Scope: "#", Directive: "0"},
 
334
                {Scope: "lxd", Directive: "1"},
 
335
                {Scope: "lxd", Directive: ""},
 
336
        }
 
337
        _, err := juju.DeployApplication(f,
 
338
                juju.DeployApplicationParams{
 
339
                        ApplicationName: "bob",
 
340
                        Charm:           s.charm,
 
341
                        Constraints:     serviceCons,
 
342
                        NumUnits:        4,
 
343
                        Placement:       placement,
 
344
                })
 
345
        c.Assert(err, jc.ErrorIsNil)
 
346
 
 
347
        c.Assert(f.args.Name, gc.Equals, "bob")
 
348
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
349
        c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
 
350
        c.Assert(f.args.NumUnits, gc.Equals, 4)
 
351
        c.Assert(f.args.Placement, gc.DeepEquals, placement)
 
352
}
 
353
 
 
354
func (s *DeployLocalSuite) TestDeployWithFewerPlacement(c *gc.C) {
 
355
        f := &fakeDeployer{State: s.State}
 
356
        serviceCons := constraints.MustParse("cpu-cores=2")
 
357
        placement := []*instance.Placement{{Scope: s.State.ModelUUID(), Directive: "valid"}}
 
358
        _, err := juju.DeployApplication(f,
 
359
                juju.DeployApplicationParams{
 
360
                        ApplicationName: "bob",
 
361
                        Charm:           s.charm,
 
362
                        Constraints:     serviceCons,
 
363
                        NumUnits:        3,
 
364
                        Placement:       placement,
 
365
                })
 
366
        c.Assert(err, jc.ErrorIsNil)
 
367
        c.Assert(f.args.Name, gc.Equals, "bob")
 
368
        c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
 
369
        c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
 
370
        c.Assert(f.args.NumUnits, gc.Equals, 3)
 
371
        c.Assert(f.args.Placement, gc.DeepEquals, placement)
 
372
}
 
373
 
 
374
func (s *DeployLocalSuite) assertAssignedUnit(c *gc.C, u *state.Unit, mId string, cons constraints.Value) {
 
375
        id, err := u.AssignedMachineId()
 
376
        c.Assert(err, jc.ErrorIsNil)
 
377
        machine, err := s.State.Machine(id)
 
378
        c.Assert(err, jc.ErrorIsNil)
 
379
        machineCons, err := machine.Constraints()
 
380
        c.Assert(err, jc.ErrorIsNil)
 
381
        c.Assert(machineCons, gc.DeepEquals, cons)
 
382
}
 
383
 
 
384
func (s *DeployLocalSuite) assertCharm(c *gc.C, service *state.Application, expect *charm.URL) {
 
385
        curl, force := service.CharmURL()
 
386
        c.Assert(curl, gc.DeepEquals, expect)
 
387
        c.Assert(force, jc.IsFalse)
 
388
}
 
389
 
 
390
func (s *DeployLocalSuite) assertSettings(c *gc.C, service *state.Application, expect charm.Settings) {
 
391
        settings, err := service.ConfigSettings()
 
392
        c.Assert(err, jc.ErrorIsNil)
 
393
        c.Assert(settings, gc.DeepEquals, expect)
 
394
}
 
395
 
 
396
func (s *DeployLocalSuite) assertConstraints(c *gc.C, service *state.Application, expect constraints.Value) {
 
397
        cons, err := service.Constraints()
 
398
        c.Assert(err, jc.ErrorIsNil)
 
399
        c.Assert(cons, gc.DeepEquals, expect)
 
400
}
 
401
 
 
402
func (s *DeployLocalSuite) assertMachines(c *gc.C, service *state.Application, expectCons constraints.Value, expectIds ...string) {
 
403
        units, err := service.AllUnits()
 
404
        c.Assert(err, jc.ErrorIsNil)
 
405
        c.Assert(units, gc.HasLen, len(expectIds))
 
406
        // first manually tell state to assign all the units
 
407
        for _, unit := range units {
 
408
                id := unit.Tag().Id()
 
409
                res, err := s.State.AssignStagedUnits([]string{id})
 
410
                c.Assert(err, jc.ErrorIsNil)
 
411
                c.Assert(res[0].Error, jc.ErrorIsNil)
 
412
                c.Assert(res[0].Unit, gc.Equals, id)
 
413
        }
 
414
 
 
415
        // refresh the list of units from state
 
416
        units, err = service.AllUnits()
 
417
        c.Assert(err, jc.ErrorIsNil)
 
418
        c.Assert(units, gc.HasLen, len(expectIds))
 
419
        unseenIds := set.NewStrings(expectIds...)
 
420
        for _, unit := range units {
 
421
                id, err := unit.AssignedMachineId()
 
422
                c.Assert(err, jc.ErrorIsNil)
 
423
                unseenIds.Remove(id)
 
424
                machine, err := s.State.Machine(id)
 
425
                c.Assert(err, jc.ErrorIsNil)
 
426
                cons, err := machine.Constraints()
 
427
                c.Assert(err, jc.ErrorIsNil)
 
428
                c.Assert(cons, gc.DeepEquals, expectCons)
 
429
        }
 
430
        c.Assert(unseenIds, gc.DeepEquals, set.NewStrings())
 
431
}
 
432
 
 
433
type fakeDeployer struct {
 
434
        *state.State
 
435
        args state.AddApplicationArgs
 
436
}
 
437
 
 
438
func (f *fakeDeployer) AddApplication(args state.AddApplicationArgs) (*state.Application, error) {
 
439
        f.args = args
 
440
        return nil, nil
 
441
}