~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/upgrades/upgrade_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 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package upgrades_test
 
5
 
 
6
import (
 
7
        "errors"
 
8
        "fmt"
 
9
        "path/filepath"
 
10
        "strings"
 
11
        stdtesting "testing"
 
12
 
 
13
        jc "github.com/juju/testing/checkers"
 
14
        "github.com/juju/version"
 
15
        gc "gopkg.in/check.v1"
 
16
        "gopkg.in/juju/names.v2"
 
17
 
 
18
        "github.com/juju/juju/agent"
 
19
        "github.com/juju/juju/api"
 
20
        "github.com/juju/juju/apiserver/params"
 
21
        "github.com/juju/juju/mongo"
 
22
        "github.com/juju/juju/state"
 
23
        "github.com/juju/juju/state/multiwatcher"
 
24
        coretesting "github.com/juju/juju/testing"
 
25
        "github.com/juju/juju/upgrades"
 
26
        jujuversion "github.com/juju/juju/version"
 
27
)
 
28
 
 
29
func TestPackage(t *stdtesting.T) {
 
30
        coretesting.MgoTestPackage(t)
 
31
}
 
32
 
 
33
// assertStateSteps is a helper that ensures that the given
 
34
// state-based upgrade steps match what is expected for that version
 
35
// and that the steps have been added to the global upgrade operations
 
36
// list.
 
37
func assertStateSteps(c *gc.C, ver version.Number, expectedSteps []string) {
 
38
        findAndCheckSteps(c, (*upgrades.StateUpgradeOperations)(), ver, expectedSteps)
 
39
}
 
40
 
 
41
// assertSteps is a helper that ensures that the given API-based
 
42
// upgrade steps match what is expected for that version and that the
 
43
// steps have been added to the global upgrade operations list.
 
44
func assertSteps(c *gc.C, ver version.Number, expectedSteps []string) {
 
45
        findAndCheckSteps(c, (*upgrades.UpgradeOperations)(), ver, expectedSteps)
 
46
}
 
47
 
 
48
func findAndCheckSteps(c *gc.C, ops []upgrades.Operation, ver version.Number, expectedSteps []string) {
 
49
        for _, op := range ops {
 
50
                if op.TargetVersion() == ver {
 
51
                        assertExpectedSteps(c, op.Steps(), expectedSteps)
 
52
                        return
 
53
                }
 
54
        }
 
55
        if len(expectedSteps) > 0 {
 
56
                c.Fatal("upgrade operations for this version are not hooked up")
 
57
        }
 
58
}
 
59
 
 
60
// assertExpectedSteps is a helper function used to check that the upgrade steps match
 
61
// what is expected for a version.
 
62
func assertExpectedSteps(c *gc.C, steps []upgrades.Step, expectedSteps []string) {
 
63
        c.Assert(steps, gc.HasLen, len(expectedSteps))
 
64
 
 
65
        var stepNames = make([]string, len(steps))
 
66
        for i, step := range steps {
 
67
                stepNames[i] = step.Description()
 
68
        }
 
69
        c.Assert(stepNames, gc.DeepEquals, expectedSteps)
 
70
}
 
71
 
 
72
type upgradeSuite struct {
 
73
        coretesting.BaseSuite
 
74
}
 
75
 
 
76
var _ = gc.Suite(&upgradeSuite{})
 
77
 
 
78
type mockUpgradeOperation struct {
 
79
        targetVersion version.Number
 
80
        steps         []upgrades.Step
 
81
}
 
82
 
 
83
func (m *mockUpgradeOperation) TargetVersion() version.Number {
 
84
        return m.targetVersion
 
85
}
 
86
 
 
87
func (m *mockUpgradeOperation) Steps() []upgrades.Step {
 
88
        return m.steps
 
89
}
 
90
 
 
91
type mockUpgradeStep struct {
 
92
        msg     string
 
93
        targets []upgrades.Target
 
94
}
 
95
 
 
96
func (u *mockUpgradeStep) Description() string {
 
97
        return u.msg
 
98
}
 
99
 
 
100
func (u *mockUpgradeStep) Targets() []upgrades.Target {
 
101
        return u.targets
 
102
}
 
103
 
 
104
func (u *mockUpgradeStep) Run(ctx upgrades.Context) error {
 
105
        if strings.HasSuffix(u.msg, "error") {
 
106
                return errors.New("upgrade error occurred")
 
107
        }
 
108
        context := ctx.(*mockContext)
 
109
        context.messages = append(context.messages, u.msg)
 
110
        return nil
 
111
}
 
112
 
 
113
func newUpgradeStep(msg string, targets ...upgrades.Target) *mockUpgradeStep {
 
114
        if len(targets) < 1 {
 
115
                panic(fmt.Sprintf("step %q must have at least one target", msg))
 
116
        }
 
117
        return &mockUpgradeStep{
 
118
                msg:     msg,
 
119
                targets: targets,
 
120
        }
 
121
}
 
122
 
 
123
type mockContext struct {
 
124
        messages        []string
 
125
        agentConfig     *mockAgentConfig
 
126
        realAgentConfig agent.ConfigSetter
 
127
        apiState        api.Connection
 
128
        state           *state.State
 
129
}
 
130
 
 
131
func (c *mockContext) APIState() api.Connection {
 
132
        return c.apiState
 
133
}
 
134
 
 
135
func (c *mockContext) State() *state.State {
 
136
        return c.state
 
137
}
 
138
 
 
139
func (c *mockContext) AgentConfig() agent.ConfigSetter {
 
140
        if c.realAgentConfig != nil {
 
141
                return c.realAgentConfig
 
142
        }
 
143
        return c.agentConfig
 
144
}
 
145
 
 
146
func (c *mockContext) StateContext() upgrades.Context {
 
147
        return c
 
148
}
 
149
 
 
150
func (c *mockContext) APIContext() upgrades.Context {
 
151
        return c
 
152
}
 
153
 
 
154
type mockAgentConfig struct {
 
155
        agent.ConfigSetter
 
156
        dataDir      string
 
157
        logDir       string
 
158
        tag          names.Tag
 
159
        jobs         []multiwatcher.MachineJob
 
160
        apiAddresses []string
 
161
        values       map[string]string
 
162
        mongoInfo    *mongo.MongoInfo
 
163
        servingInfo  params.StateServingInfo
 
164
        modelTag     names.ModelTag
 
165
}
 
166
 
 
167
func (mock *mockAgentConfig) Tag() names.Tag {
 
168
        return mock.tag
 
169
}
 
170
 
 
171
func (mock *mockAgentConfig) DataDir() string {
 
172
        return mock.dataDir
 
173
}
 
174
 
 
175
func (mock *mockAgentConfig) LogDir() string {
 
176
        return mock.logDir
 
177
}
 
178
 
 
179
func (mock *mockAgentConfig) SystemIdentityPath() string {
 
180
        return filepath.Join(mock.dataDir, agent.SystemIdentity)
 
181
}
 
182
 
 
183
func (mock *mockAgentConfig) Jobs() []multiwatcher.MachineJob {
 
184
        return mock.jobs
 
185
}
 
186
 
 
187
func (mock *mockAgentConfig) APIAddresses() ([]string, error) {
 
188
        return mock.apiAddresses, nil
 
189
}
 
190
 
 
191
func (mock *mockAgentConfig) Value(name string) string {
 
192
        return mock.values[name]
 
193
}
 
194
 
 
195
func (mock *mockAgentConfig) MongoInfo() (*mongo.MongoInfo, bool) {
 
196
        return mock.mongoInfo, true
 
197
}
 
198
 
 
199
func (mock *mockAgentConfig) StateServingInfo() (params.StateServingInfo, bool) {
 
200
        return mock.servingInfo, true
 
201
}
 
202
 
 
203
func (mock *mockAgentConfig) SetStateServingInfo(info params.StateServingInfo) {
 
204
        mock.servingInfo = info
 
205
}
 
206
 
 
207
func (mock *mockAgentConfig) Model() names.ModelTag {
 
208
        return mock.modelTag
 
209
}
 
210
 
 
211
func stateUpgradeOperations() []upgrades.Operation {
 
212
        steps := []upgrades.Operation{
 
213
                &mockUpgradeOperation{
 
214
                        targetVersion: version.MustParse("1.11.0"),
 
215
                        steps: []upgrades.Step{
 
216
                                newUpgradeStep("state step 1 - 1.11.0", upgrades.Controller),
 
217
                                newUpgradeStep("state step 2 error", upgrades.Controller),
 
218
                                newUpgradeStep("state step 3 - 1.11.0", upgrades.Controller),
 
219
                        },
 
220
                },
 
221
                &mockUpgradeOperation{
 
222
                        targetVersion: version.MustParse("1.21.0"),
 
223
                        steps: []upgrades.Step{
 
224
                                newUpgradeStep("state step 1 - 1.21.0", upgrades.DatabaseMaster),
 
225
                                newUpgradeStep("state step 2 - 1.21.0", upgrades.Controller),
 
226
                        },
 
227
                },
 
228
                &mockUpgradeOperation{
 
229
                        targetVersion: version.MustParse("1.22.0"),
 
230
                        steps: []upgrades.Step{
 
231
                                newUpgradeStep("state step 1 - 1.22.0", upgrades.DatabaseMaster),
 
232
                                newUpgradeStep("state step 2 - 1.22.0", upgrades.Controller),
 
233
                        },
 
234
                },
 
235
        }
 
236
        return steps
 
237
}
 
238
 
 
239
func upgradeOperations() []upgrades.Operation {
 
240
        steps := []upgrades.Operation{
 
241
                &mockUpgradeOperation{
 
242
                        targetVersion: version.MustParse("1.12.0"),
 
243
                        steps: []upgrades.Step{
 
244
                                newUpgradeStep("step 1 - 1.12.0", upgrades.AllMachines),
 
245
                                newUpgradeStep("step 2 error", upgrades.HostMachine),
 
246
                                newUpgradeStep("step 3", upgrades.HostMachine),
 
247
                        },
 
248
                },
 
249
                &mockUpgradeOperation{
 
250
                        targetVersion: version.MustParse("1.16.0"),
 
251
                        steps: []upgrades.Step{
 
252
                                newUpgradeStep("step 1 - 1.16.0", upgrades.HostMachine),
 
253
                                newUpgradeStep("step 2 - 1.16.0", upgrades.HostMachine),
 
254
                                newUpgradeStep("step 3 - 1.16.0", upgrades.Controller),
 
255
                        },
 
256
                },
 
257
                &mockUpgradeOperation{
 
258
                        targetVersion: version.MustParse("1.17.0"),
 
259
                        steps: []upgrades.Step{
 
260
                                newUpgradeStep("step 1 - 1.17.0", upgrades.HostMachine),
 
261
                        },
 
262
                },
 
263
                &mockUpgradeOperation{
 
264
                        targetVersion: version.MustParse("1.17.1"),
 
265
                        steps: []upgrades.Step{
 
266
                                newUpgradeStep("step 1 - 1.17.1", upgrades.HostMachine),
 
267
                                newUpgradeStep("step 2 - 1.17.1", upgrades.Controller),
 
268
                        },
 
269
                },
 
270
                &mockUpgradeOperation{
 
271
                        targetVersion: version.MustParse("1.18.0"),
 
272
                        steps: []upgrades.Step{
 
273
                                newUpgradeStep("step 1 - 1.18.0", upgrades.HostMachine),
 
274
                                newUpgradeStep("step 2 - 1.18.0", upgrades.Controller),
 
275
                        },
 
276
                },
 
277
                &mockUpgradeOperation{
 
278
                        targetVersion: version.MustParse("1.20.0"),
 
279
                        steps: []upgrades.Step{
 
280
                                newUpgradeStep("step 1 - 1.20.0", upgrades.AllMachines),
 
281
                                newUpgradeStep("step 2 - 1.20.0", upgrades.HostMachine),
 
282
                                newUpgradeStep("step 3 - 1.20.0", upgrades.Controller),
 
283
                        },
 
284
                },
 
285
                &mockUpgradeOperation{
 
286
                        targetVersion: version.MustParse("1.21.0"),
 
287
                        steps: []upgrades.Step{
 
288
                                newUpgradeStep("step 1 - 1.21.0", upgrades.AllMachines),
 
289
                        },
 
290
                },
 
291
                &mockUpgradeOperation{
 
292
                        targetVersion: version.MustParse("1.22.0"),
 
293
                        steps: []upgrades.Step{
 
294
                                // Separate targets used intentionally
 
295
                                newUpgradeStep("step 1 - 1.22.0", upgrades.Controller, upgrades.HostMachine),
 
296
                                newUpgradeStep("step 2 - 1.22.0", upgrades.AllMachines),
 
297
                        },
 
298
                },
 
299
        }
 
300
        return steps
 
301
}
 
302
 
 
303
type areUpgradesDefinedTest struct {
 
304
        about       string
 
305
        fromVersion string
 
306
        toVersion   string
 
307
        expected    bool
 
308
        err         string
 
309
}
 
310
 
 
311
var areUpgradesDefinedTests = []areUpgradesDefinedTest{
 
312
        {
 
313
                about:       "no ops if same version",
 
314
                fromVersion: "1.18.0",
 
315
                expected:    false,
 
316
        },
 
317
        {
 
318
                about:       "true when ops defined between versions",
 
319
                fromVersion: "1.17.1",
 
320
                expected:    true,
 
321
        },
 
322
        {
 
323
                about:       "false when no ops defined between versions",
 
324
                fromVersion: "1.13.0",
 
325
                toVersion:   "1.14.1",
 
326
                expected:    false,
 
327
        },
 
328
        {
 
329
                about:       "true when just state ops defined ",
 
330
                fromVersion: "1.10.0",
 
331
                toVersion:   "1.11.0",
 
332
                expected:    true,
 
333
        },
 
334
        {
 
335
                about:       "from version is defaulted when not supplied",
 
336
                fromVersion: "",
 
337
                expected:    true,
 
338
        },
 
339
        {
 
340
                about:       "upgrade between pre-final versions",
 
341
                fromVersion: "1.21-beta4",
 
342
                toVersion:   "1.21-beta5",
 
343
                expected:    true,
 
344
        },
 
345
        {
 
346
                about:       "no upgrades when version hasn't changed, even with release tags",
 
347
                fromVersion: "1.21-beta5",
 
348
                toVersion:   "1.21-beta5",
 
349
                expected:    false,
 
350
        },
 
351
}
 
352
 
 
353
func (s *upgradeSuite) TestAreUpgradesDefined(c *gc.C) {
 
354
        s.PatchValue(upgrades.StateUpgradeOperations, stateUpgradeOperations)
 
355
        s.PatchValue(upgrades.UpgradeOperations, upgradeOperations)
 
356
        for i, test := range areUpgradesDefinedTests {
 
357
                c.Logf("%d: %s", i, test.about)
 
358
                fromVersion := version.Zero
 
359
                if test.fromVersion != "" {
 
360
                        fromVersion = version.MustParse(test.fromVersion)
 
361
                }
 
362
                toVersion := version.MustParse("1.18.0")
 
363
                if test.toVersion != "" {
 
364
                        toVersion = version.MustParse(test.toVersion)
 
365
                }
 
366
                s.PatchValue(&jujuversion.Current, toVersion)
 
367
                result := upgrades.AreUpgradesDefined(fromVersion)
 
368
                c.Check(result, gc.Equals, test.expected)
 
369
        }
 
370
}
 
371
 
 
372
type upgradeTest struct {
 
373
        about         string
 
374
        fromVersion   string
 
375
        toVersion     string
 
376
        targets       []upgrades.Target
 
377
        expectedSteps []string
 
378
        err           string
 
379
}
 
380
 
 
381
func targets(t ...upgrades.Target) []upgrades.Target {
 
382
        return t
 
383
}
 
384
 
 
385
var upgradeTests = []upgradeTest{
 
386
        {
 
387
                about:         "from version excludes steps for same version",
 
388
                fromVersion:   "1.18.0",
 
389
                targets:       targets(upgrades.HostMachine),
 
390
                expectedSteps: []string{},
 
391
        },
 
392
        {
 
393
                about:         "target version excludes steps for newer version",
 
394
                toVersion:     "1.17.1",
 
395
                targets:       targets(upgrades.HostMachine),
 
396
                expectedSteps: []string{"step 1 - 1.17.0", "step 1 - 1.17.1"},
 
397
        },
 
398
        {
 
399
                about:         "from version excludes older steps",
 
400
                fromVersion:   "1.17.0",
 
401
                targets:       targets(upgrades.HostMachine),
 
402
                expectedSteps: []string{"step 1 - 1.17.1", "step 1 - 1.18.0"},
 
403
        },
 
404
        {
 
405
                about:         "incompatible targets excluded",
 
406
                fromVersion:   "1.17.1",
 
407
                targets:       targets(upgrades.Controller),
 
408
                expectedSteps: []string{"step 2 - 1.18.0"},
 
409
        },
 
410
        {
 
411
                about:         "allMachines matches everything",
 
412
                fromVersion:   "1.18.1",
 
413
                toVersion:     "1.20.0",
 
414
                targets:       targets(upgrades.HostMachine),
 
415
                expectedSteps: []string{"step 1 - 1.20.0", "step 2 - 1.20.0"},
 
416
        },
 
417
        {
 
418
                about:         "allMachines matches everything",
 
419
                fromVersion:   "1.18.1",
 
420
                toVersion:     "1.20.0",
 
421
                targets:       targets(upgrades.Controller),
 
422
                expectedSteps: []string{"step 1 - 1.20.0", "step 3 - 1.20.0"},
 
423
        },
 
424
        {
 
425
                about:         "state step error aborts, subsequent state steps not run",
 
426
                fromVersion:   "1.10.0",
 
427
                targets:       targets(upgrades.Controller),
 
428
                expectedSteps: []string{"state step 1 - 1.11.0"},
 
429
                err:           "state step 2 error: upgrade error occurred",
 
430
        },
 
431
        {
 
432
                about:         "error aborts, subsequent steps not run",
 
433
                fromVersion:   "1.11.0",
 
434
                targets:       targets(upgrades.HostMachine),
 
435
                expectedSteps: []string{"step 1 - 1.12.0"},
 
436
                err:           "step 2 error: upgrade error occurred",
 
437
        },
 
438
        {
 
439
                about:         "default from version is 1.16",
 
440
                fromVersion:   "",
 
441
                targets:       targets(upgrades.Controller),
 
442
                expectedSteps: []string{"step 2 - 1.17.1", "step 2 - 1.18.0"},
 
443
        },
 
444
        {
 
445
                about:         "controllers don't get database master",
 
446
                fromVersion:   "1.20.0",
 
447
                toVersion:     "1.21.0",
 
448
                targets:       targets(upgrades.Controller),
 
449
                expectedSteps: []string{"state step 2 - 1.21.0", "step 1 - 1.21.0"},
 
450
        },
 
451
        {
 
452
                about:         "database master only (not actually possible in reality)",
 
453
                fromVersion:   "1.20.0",
 
454
                toVersion:     "1.21.0",
 
455
                targets:       targets(upgrades.DatabaseMaster),
 
456
                expectedSteps: []string{"state step 1 - 1.21.0", "step 1 - 1.21.0"},
 
457
        },
 
458
        {
 
459
                about:       "all state steps are run first",
 
460
                fromVersion: "1.20.0",
 
461
                toVersion:   "1.22.0",
 
462
                targets:     targets(upgrades.DatabaseMaster, upgrades.Controller),
 
463
                expectedSteps: []string{
 
464
                        "state step 1 - 1.21.0", "state step 2 - 1.21.0",
 
465
                        "state step 1 - 1.22.0", "state step 2 - 1.22.0",
 
466
                        "step 1 - 1.21.0",
 
467
                        "step 1 - 1.22.0", "step 2 - 1.22.0",
 
468
                },
 
469
        },
 
470
        {
 
471
                about:         "machine with multiple targets - each step only run once",
 
472
                fromVersion:   "1.20.0",
 
473
                toVersion:     "1.21.0",
 
474
                targets:       targets(upgrades.HostMachine, upgrades.Controller),
 
475
                expectedSteps: []string{"state step 2 - 1.21.0", "step 1 - 1.21.0"},
 
476
        },
 
477
        {
 
478
                about:         "step with multiple targets",
 
479
                fromVersion:   "1.21.0",
 
480
                toVersion:     "1.22.0",
 
481
                targets:       targets(upgrades.HostMachine),
 
482
                expectedSteps: []string{"step 1 - 1.22.0", "step 2 - 1.22.0"},
 
483
        },
 
484
        {
 
485
                about:         "machine and step with multiple targets - each step only run once",
 
486
                fromVersion:   "1.21.0",
 
487
                toVersion:     "1.22.0",
 
488
                targets:       targets(upgrades.HostMachine, upgrades.Controller),
 
489
                expectedSteps: []string{"state step 2 - 1.22.0", "step 1 - 1.22.0", "step 2 - 1.22.0"},
 
490
        },
 
491
        {
 
492
                about:         "upgrade to alpha release runs steps for final release",
 
493
                fromVersion:   "1.20.0",
 
494
                toVersion:     "1.21-alpha1",
 
495
                targets:       targets(upgrades.HostMachine),
 
496
                expectedSteps: []string{"step 1 - 1.21.0"},
 
497
        },
 
498
        {
 
499
                about:         "upgrade to beta release runs steps for final release",
 
500
                fromVersion:   "1.20.0",
 
501
                toVersion:     "1.21-beta2",
 
502
                targets:       targets(upgrades.HostMachine),
 
503
                expectedSteps: []string{"step 1 - 1.21.0"},
 
504
        },
 
505
        {
 
506
                about:         "starting release steps included when upgrading from an alpha release",
 
507
                fromVersion:   "1.20-alpha3",
 
508
                toVersion:     "1.21.0",
 
509
                targets:       targets(upgrades.HostMachine),
 
510
                expectedSteps: []string{"step 1 - 1.20.0", "step 2 - 1.20.0", "step 1 - 1.21.0"},
 
511
        },
 
512
        {
 
513
                about:         "starting release steps included when upgrading from an beta release",
 
514
                fromVersion:   "1.20-beta1",
 
515
                toVersion:     "1.21.0",
 
516
                targets:       targets(upgrades.HostMachine),
 
517
                expectedSteps: []string{"step 1 - 1.20.0", "step 2 - 1.20.0", "step 1 - 1.21.0"},
 
518
        },
 
519
        {
 
520
                about:         "nothing happens when the version hasn't changed but contains a tag",
 
521
                fromVersion:   "1.21-alpha1",
 
522
                toVersion:     "1.21-alpha1",
 
523
                targets:       targets(upgrades.DatabaseMaster),
 
524
                expectedSteps: []string{},
 
525
        },
 
526
        {
 
527
                about:         "upgrades between pre-final versions should run steps for the final version",
 
528
                fromVersion:   "1.21-beta2",
 
529
                toVersion:     "1.21-beta3",
 
530
                targets:       targets(upgrades.DatabaseMaster),
 
531
                expectedSteps: []string{"state step 1 - 1.21.0", "step 1 - 1.21.0"},
 
532
        },
 
533
}
 
534
 
 
535
func (s *upgradeSuite) TestPerformUpgrade(c *gc.C) {
 
536
        s.PatchValue(upgrades.StateUpgradeOperations, stateUpgradeOperations)
 
537
        s.PatchValue(upgrades.UpgradeOperations, upgradeOperations)
 
538
        for i, test := range upgradeTests {
 
539
                c.Logf("%d: %s", i, test.about)
 
540
                var messages []string
 
541
                ctx := &mockContext{
 
542
                        messages: messages,
 
543
                }
 
544
                fromVersion := version.Zero
 
545
                if test.fromVersion != "" {
 
546
                        fromVersion = version.MustParse(test.fromVersion)
 
547
                }
 
548
                toVersion := version.MustParse("1.18.0")
 
549
                if test.toVersion != "" {
 
550
                        toVersion = version.MustParse(test.toVersion)
 
551
                }
 
552
                s.PatchValue(&jujuversion.Current, toVersion)
 
553
                err := upgrades.PerformUpgrade(fromVersion, test.targets, ctx)
 
554
                if test.err == "" {
 
555
                        c.Check(err, jc.ErrorIsNil)
 
556
                } else {
 
557
                        c.Check(err, gc.ErrorMatches, test.err)
 
558
                }
 
559
                c.Check(ctx.messages, jc.DeepEquals, test.expectedSteps)
 
560
        }
 
561
}
 
562
 
 
563
type contextStep struct {
 
564
        useAPI bool
 
565
}
 
566
 
 
567
func (s *contextStep) Description() string {
 
568
        return "something"
 
569
}
 
570
 
 
571
func (s *contextStep) Targets() []upgrades.Target {
 
572
        return []upgrades.Target{upgrades.Controller}
 
573
}
 
574
 
 
575
func (s *contextStep) Run(context upgrades.Context) error {
 
576
        if s.useAPI {
 
577
                context.APIState()
 
578
        } else {
 
579
                context.State()
 
580
        }
 
581
        return nil
 
582
}
 
583
 
 
584
func (s *upgradeSuite) TestStateStepsGetRestrictedContext(c *gc.C) {
 
585
        s.PatchValue(upgrades.StateUpgradeOperations, func() []upgrades.Operation {
 
586
                return []upgrades.Operation{
 
587
                        &mockUpgradeOperation{
 
588
                                targetVersion: version.MustParse("1.21.0"),
 
589
                                steps:         []upgrades.Step{&contextStep{useAPI: true}},
 
590
                        },
 
591
                }
 
592
        })
 
593
 
 
594
        s.PatchValue(upgrades.UpgradeOperations,
 
595
                func() []upgrades.Operation { return nil })
 
596
 
 
597
        s.checkContextRestriction(c, "API not available from this context")
 
598
}
 
599
 
 
600
func (s *upgradeSuite) TestApiStepsGetRestrictedContext(c *gc.C) {
 
601
        s.PatchValue(upgrades.StateUpgradeOperations,
 
602
                func() []upgrades.Operation { return nil })
 
603
 
 
604
        s.PatchValue(upgrades.UpgradeOperations, func() []upgrades.Operation {
 
605
                return []upgrades.Operation{
 
606
                        &mockUpgradeOperation{
 
607
                                targetVersion: version.MustParse("1.21.0"),
 
608
                                steps:         []upgrades.Step{&contextStep{useAPI: false}},
 
609
                        },
 
610
                }
 
611
        })
 
612
 
 
613
        s.checkContextRestriction(c, "State not available from this context")
 
614
}
 
615
 
 
616
func (s *upgradeSuite) checkContextRestriction(c *gc.C, expectedPanic string) {
 
617
        fromVersion := version.MustParse("1.20.0")
 
618
        type fakeAgentConfigSetter struct{ agent.ConfigSetter }
 
619
        ctx := upgrades.NewContext(fakeAgentConfigSetter{}, nil, new(state.State))
 
620
        c.Assert(
 
621
                func() { upgrades.PerformUpgrade(fromVersion, targets(upgrades.Controller), ctx) },
 
622
                gc.PanicMatches, expectedPanic,
 
623
        )
 
624
}
 
625
 
 
626
func (s *upgradeSuite) TestStateStepsNotAttemptedWhenNoStateTarget(c *gc.C) {
 
627
        stateCount := 0
 
628
        stateUpgradeOperations := func() []upgrades.Operation {
 
629
                stateCount++
 
630
                return nil
 
631
        }
 
632
        s.PatchValue(upgrades.StateUpgradeOperations, stateUpgradeOperations)
 
633
 
 
634
        apiCount := 0
 
635
        upgradeOperations := func() []upgrades.Operation {
 
636
                apiCount++
 
637
                return nil
 
638
        }
 
639
        s.PatchValue(upgrades.UpgradeOperations, upgradeOperations)
 
640
 
 
641
        fromVers := version.MustParse("1.18.0")
 
642
        ctx := new(mockContext)
 
643
        check := func(target upgrades.Target, expectedStateCallCount int) {
 
644
                stateCount = 0
 
645
                apiCount = 0
 
646
                err := upgrades.PerformUpgrade(fromVers, targets(target), ctx)
 
647
                c.Assert(err, jc.ErrorIsNil)
 
648
                c.Assert(stateCount, gc.Equals, expectedStateCallCount)
 
649
                c.Assert(apiCount, gc.Equals, 1)
 
650
        }
 
651
 
 
652
        check(upgrades.Controller, 1)
 
653
        check(upgrades.DatabaseMaster, 1)
 
654
        check(upgrades.AllMachines, 0)
 
655
        check(upgrades.HostMachine, 0)
 
656
}
 
657
 
 
658
func (s *upgradeSuite) TestUpgradeOperationsOrdered(c *gc.C) {
 
659
        var previous version.Number
 
660
        for i, utv := range (*upgrades.UpgradeOperations)() {
 
661
                vers := utv.TargetVersion()
 
662
                if i > 0 {
 
663
                        c.Check(previous.Compare(vers), gc.Equals, -1)
 
664
                }
 
665
                previous = vers
 
666
        }
 
667
}
 
668
 
 
669
func (s *upgradeSuite) TestStateUpgradeOperationsVersions(c *gc.C) {
 
670
        versions := extractUpgradeVersions(c, (*upgrades.StateUpgradeOperations)())
 
671
        c.Assert(versions, gc.DeepEquals, []string{
 
672
                "1.26-placeholder1",
 
673
        })
 
674
}
 
675
 
 
676
func (s *upgradeSuite) TestUpgradeOperationsVersions(c *gc.C) {
 
677
        versions := extractUpgradeVersions(c, (*upgrades.UpgradeOperations)())
 
678
        c.Assert(versions, gc.DeepEquals, []string{
 
679
                "1.26-placeholder1",
 
680
        })
 
681
}
 
682
 
 
683
func extractUpgradeVersions(c *gc.C, ops []upgrades.Operation) []string {
 
684
        var versions []string
 
685
        for _, utv := range ops {
 
686
                vers := utv.TargetVersion()
 
687
                // Upgrade steps should only be targeted at final versions (not alpha/beta).
 
688
                c.Check(vers.Tag, gc.Equals, "placeholder")
 
689
                versions = append(versions, vers.String())
 
690
        }
 
691
        return versions
 
692
}