~cloud-green/juju-core/charmstore-sdist

« back to all changes in this revision

Viewing changes to launchpad.net/juju-core/state/api/provisioner/provisioner_test.go

  • Committer: Casey Marshall
  • Date: 2014-03-27 15:59:46 UTC
  • Revision ID: cmars@cmarstech.com-20140327155946-8huorf37g0zwar43
Source distribution of launchpad.net/juju-core created 20140327105939

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package provisioner_test
 
5
 
 
6
import (
 
7
        stdtesting "testing"
 
8
 
 
9
        jc "github.com/juju/testing/checkers"
 
10
        gc "launchpad.net/gocheck"
 
11
 
 
12
        "launchpad.net/juju-core/constraints"
 
13
        "launchpad.net/juju-core/errors"
 
14
        "launchpad.net/juju-core/instance"
 
15
        "launchpad.net/juju-core/juju/testing"
 
16
        "launchpad.net/juju-core/state"
 
17
        "launchpad.net/juju-core/state/api"
 
18
        "launchpad.net/juju-core/state/api/params"
 
19
        "launchpad.net/juju-core/state/api/provisioner"
 
20
        apitesting "launchpad.net/juju-core/state/api/testing"
 
21
        statetesting "launchpad.net/juju-core/state/testing"
 
22
        coretesting "launchpad.net/juju-core/testing"
 
23
        "launchpad.net/juju-core/tools"
 
24
        "launchpad.net/juju-core/utils"
 
25
        "launchpad.net/juju-core/version"
 
26
)
 
27
 
 
28
func TestAll(t *stdtesting.T) {
 
29
        coretesting.MgoTestPackage(t)
 
30
}
 
31
 
 
32
type provisionerSuite struct {
 
33
        testing.JujuConnSuite
 
34
        *apitesting.EnvironWatcherTests
 
35
        *apitesting.APIAddresserTests
 
36
 
 
37
        st      *api.State
 
38
        machine *state.Machine
 
39
 
 
40
        provisioner *provisioner.State
 
41
}
 
42
 
 
43
var _ = gc.Suite(&provisionerSuite{})
 
44
 
 
45
func (s *provisionerSuite) SetUpTest(c *gc.C) {
 
46
        s.JujuConnSuite.SetUpTest(c)
 
47
 
 
48
        var err error
 
49
        s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron)
 
50
        c.Assert(err, gc.IsNil)
 
51
        password, err := utils.RandomPassword()
 
52
        c.Assert(err, gc.IsNil)
 
53
        err = s.machine.SetPassword(password)
 
54
        c.Assert(err, gc.IsNil)
 
55
        err = s.machine.SetProvisioned("i-manager", "fake_nonce", nil)
 
56
        c.Assert(err, gc.IsNil)
 
57
        s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce")
 
58
        c.Assert(s.st, gc.NotNil)
 
59
        err = s.machine.SetAddresses(instance.NewAddresses([]string{"0.1.2.3"}))
 
60
        c.Assert(err, gc.IsNil)
 
61
 
 
62
        // Create the provisioner API facade.
 
63
        s.provisioner = s.st.Provisioner()
 
64
        c.Assert(s.provisioner, gc.NotNil)
 
65
 
 
66
        s.EnvironWatcherTests = apitesting.NewEnvironWatcherTests(s.provisioner, s.BackingState, apitesting.HasSecrets)
 
67
        s.APIAddresserTests = apitesting.NewAPIAddresserTests(s.provisioner, s.BackingState)
 
68
}
 
69
 
 
70
func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) {
 
71
        apiMachine, err := s.provisioner.Machine("machine-42")
 
72
        c.Assert(err, gc.ErrorMatches, "machine 42 not found")
 
73
        c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
 
74
        c.Assert(apiMachine, gc.IsNil)
 
75
 
 
76
        apiMachine, err = s.provisioner.Machine(s.machine.Tag())
 
77
        c.Assert(err, gc.IsNil)
 
78
        c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag())
 
79
        c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id())
 
80
}
 
81
 
 
82
func (s *provisionerSuite) TestGetSetStatus(c *gc.C) {
 
83
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
84
        c.Assert(err, gc.IsNil)
 
85
 
 
86
        status, info, err := apiMachine.Status()
 
87
        c.Assert(err, gc.IsNil)
 
88
        c.Assert(status, gc.Equals, params.StatusPending)
 
89
        c.Assert(info, gc.Equals, "")
 
90
 
 
91
        err = apiMachine.SetStatus(params.StatusStarted, "blah", nil)
 
92
        c.Assert(err, gc.IsNil)
 
93
 
 
94
        status, info, err = apiMachine.Status()
 
95
        c.Assert(err, gc.IsNil)
 
96
        c.Assert(status, gc.Equals, params.StatusStarted)
 
97
        c.Assert(info, gc.Equals, "blah")
 
98
        _, _, data, err := s.machine.Status()
 
99
        c.Assert(err, gc.IsNil)
 
100
        c.Assert(data, gc.HasLen, 0)
 
101
}
 
102
 
 
103
func (s *provisionerSuite) TestGetSetStatusWithData(c *gc.C) {
 
104
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
105
        c.Assert(err, gc.IsNil)
 
106
 
 
107
        err = apiMachine.SetStatus(params.StatusError, "blah", params.StatusData{"foo": "bar"})
 
108
        c.Assert(err, gc.IsNil)
 
109
 
 
110
        status, info, err := apiMachine.Status()
 
111
        c.Assert(err, gc.IsNil)
 
112
        c.Assert(status, gc.Equals, params.StatusError)
 
113
        c.Assert(info, gc.Equals, "blah")
 
114
        _, _, data, err := s.machine.Status()
 
115
        c.Assert(err, gc.IsNil)
 
116
        c.Assert(data, gc.DeepEquals, params.StatusData{"foo": "bar"})
 
117
}
 
118
 
 
119
func (s *provisionerSuite) TestMachinesWithTransientErrors(c *gc.C) {
 
120
        machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
 
121
        c.Assert(err, gc.IsNil)
 
122
        err = machine.SetStatus(params.StatusError, "blah", params.StatusData{"transient": true})
 
123
        c.Assert(err, gc.IsNil)
 
124
        machines, info, err := s.provisioner.MachinesWithTransientErrors()
 
125
        c.Assert(err, gc.IsNil)
 
126
        c.Assert(machines, gc.HasLen, 1)
 
127
        c.Assert(machines[0].Id(), gc.Equals, "1")
 
128
        c.Assert(info, gc.HasLen, 1)
 
129
        c.Assert(info[0], gc.DeepEquals, params.StatusResult{
 
130
                Id:     "1",
 
131
                Life:   "alive",
 
132
                Status: "error",
 
133
                Info:   "blah",
 
134
                Data:   params.StatusData{"transient": true},
 
135
        })
 
136
}
 
137
 
 
138
func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) {
 
139
        // Create a fresh machine to test the complete scenario.
 
140
        otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
 
141
        c.Assert(err, gc.IsNil)
 
142
        c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
 
143
 
 
144
        apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
 
145
        c.Assert(err, gc.IsNil)
 
146
 
 
147
        err = apiMachine.Remove()
 
148
        c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`)
 
149
        err = apiMachine.EnsureDead()
 
150
        c.Assert(err, gc.IsNil)
 
151
 
 
152
        err = otherMachine.Refresh()
 
153
        c.Assert(err, gc.IsNil)
 
154
        c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
 
155
 
 
156
        err = apiMachine.EnsureDead()
 
157
        c.Assert(err, gc.IsNil)
 
158
        err = otherMachine.Refresh()
 
159
        c.Assert(err, gc.IsNil)
 
160
        c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
 
161
 
 
162
        err = apiMachine.Remove()
 
163
        c.Assert(err, gc.IsNil)
 
164
        err = otherMachine.Refresh()
 
165
        c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
 
166
 
 
167
        err = apiMachine.EnsureDead()
 
168
        c.Assert(err, gc.ErrorMatches, "machine 1 not found")
 
169
        c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
 
170
 
 
171
        // Now try to EnsureDead machine 0 - should fail.
 
172
        apiMachine, err = s.provisioner.Machine(s.machine.Tag())
 
173
        c.Assert(err, gc.IsNil)
 
174
        err = apiMachine.EnsureDead()
 
175
        c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment")
 
176
}
 
177
 
 
178
func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) {
 
179
        // Create a fresh machine to test the complete scenario.
 
180
        otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
 
181
        c.Assert(err, gc.IsNil)
 
182
        c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
 
183
 
 
184
        apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
 
185
        c.Assert(err, gc.IsNil)
 
186
        c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
 
187
 
 
188
        err = apiMachine.EnsureDead()
 
189
        c.Assert(err, gc.IsNil)
 
190
        c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
 
191
 
 
192
        err = apiMachine.Refresh()
 
193
        c.Assert(err, gc.IsNil)
 
194
        c.Assert(apiMachine.Life(), gc.Equals, params.Dead)
 
195
}
 
196
 
 
197
func (s *provisionerSuite) TestSetProvisionedAndInstanceId(c *gc.C) {
 
198
        // Create a fresh machine, since machine 0 is already provisioned.
 
199
        notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
 
200
        c.Assert(err, gc.IsNil)
 
201
 
 
202
        apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag())
 
203
        c.Assert(err, gc.IsNil)
 
204
 
 
205
        instanceId, err := apiMachine.InstanceId()
 
206
        c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
 
207
        c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned")
 
208
        c.Assert(instanceId, gc.Equals, instance.Id(""))
 
209
 
 
210
        hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G")
 
211
        err = apiMachine.SetProvisioned("i-will", "fake_nonce", &hwChars)
 
212
        c.Assert(err, gc.IsNil)
 
213
 
 
214
        instanceId, err = apiMachine.InstanceId()
 
215
        c.Assert(err, gc.IsNil)
 
216
        c.Assert(instanceId, gc.Equals, instance.Id("i-will"))
 
217
 
 
218
        // Try it again - should fail.
 
219
        err = apiMachine.SetProvisioned("i-wont", "fake", nil)
 
220
        c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
 
221
 
 
222
        // Now try to get machine 0's instance id.
 
223
        apiMachine, err = s.provisioner.Machine(s.machine.Tag())
 
224
        c.Assert(err, gc.IsNil)
 
225
        instanceId, err = apiMachine.InstanceId()
 
226
        c.Assert(err, gc.IsNil)
 
227
        c.Assert(instanceId, gc.Equals, instance.Id("i-manager"))
 
228
}
 
229
 
 
230
func (s *provisionerSuite) TestSeries(c *gc.C) {
 
231
        // Create a fresh machine with different series.
 
232
        foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
 
233
        c.Assert(err, gc.IsNil)
 
234
 
 
235
        apiMachine, err := s.provisioner.Machine(foobarMachine.Tag())
 
236
        c.Assert(err, gc.IsNil)
 
237
        series, err := apiMachine.Series()
 
238
        c.Assert(err, gc.IsNil)
 
239
        c.Assert(series, gc.Equals, "foobar")
 
240
 
 
241
        // Now try machine 0.
 
242
        apiMachine, err = s.provisioner.Machine(s.machine.Tag())
 
243
        c.Assert(err, gc.IsNil)
 
244
        series, err = apiMachine.Series()
 
245
        c.Assert(err, gc.IsNil)
 
246
        c.Assert(series, gc.Equals, "quantal")
 
247
}
 
248
 
 
249
func (s *provisionerSuite) TestConstraints(c *gc.C) {
 
250
        // Create a fresh machine with some constraints.
 
251
        template := state.MachineTemplate{
 
252
                Series:      "quantal",
 
253
                Jobs:        []state.MachineJob{state.JobHostUnits},
 
254
                Constraints: constraints.MustParse("cpu-cores=12", "mem=8G"),
 
255
        }
 
256
        consMachine, err := s.State.AddOneMachine(template)
 
257
        c.Assert(err, gc.IsNil)
 
258
 
 
259
        apiMachine, err := s.provisioner.Machine(consMachine.Tag())
 
260
        c.Assert(err, gc.IsNil)
 
261
        cons, err := apiMachine.Constraints()
 
262
        c.Assert(err, gc.IsNil)
 
263
        c.Assert(cons, gc.DeepEquals, template.Constraints)
 
264
 
 
265
        // Now try machine 0.
 
266
        apiMachine, err = s.provisioner.Machine(s.machine.Tag())
 
267
        c.Assert(err, gc.IsNil)
 
268
        cons, err = apiMachine.Constraints()
 
269
        c.Assert(err, gc.IsNil)
 
270
        c.Assert(cons, gc.DeepEquals, constraints.Value{})
 
271
}
 
272
 
 
273
func (s *provisionerSuite) TestWatchContainers(c *gc.C) {
 
274
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
275
        c.Assert(err, gc.IsNil)
 
276
 
 
277
        // Add one LXC container.
 
278
        template := state.MachineTemplate{
 
279
                Series: "quantal",
 
280
                Jobs:   []state.MachineJob{state.JobHostUnits},
 
281
        }
 
282
        container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
 
283
        c.Assert(err, gc.IsNil)
 
284
 
 
285
        w, err := apiMachine.WatchContainers(instance.LXC)
 
286
        c.Assert(err, gc.IsNil)
 
287
        defer statetesting.AssertStop(c, w)
 
288
        wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
 
289
 
 
290
        // Initial event.
 
291
        wc.AssertChange(container.Id())
 
292
 
 
293
        // Change something other than the containers and make sure it's
 
294
        // not detected.
 
295
        err = apiMachine.SetStatus(params.StatusStarted, "not really", nil)
 
296
        c.Assert(err, gc.IsNil)
 
297
        wc.AssertNoChange()
 
298
 
 
299
        // Add a KVM container and make sure it's not detected.
 
300
        container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM)
 
301
        c.Assert(err, gc.IsNil)
 
302
        wc.AssertNoChange()
 
303
 
 
304
        // Add another LXC container and make sure it's detected.
 
305
        container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
 
306
        c.Assert(err, gc.IsNil)
 
307
        wc.AssertChange(container.Id())
 
308
 
 
309
        statetesting.AssertStop(c, w)
 
310
        wc.AssertClosed()
 
311
}
 
312
 
 
313
func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) {
 
314
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
315
        c.Assert(err, gc.IsNil)
 
316
 
 
317
        for _, ctype := range instance.ContainerTypes {
 
318
                w, err := apiMachine.WatchContainers(ctype)
 
319
                c.Assert(w, gc.NotNil)
 
320
                c.Assert(err, gc.IsNil)
 
321
        }
 
322
}
 
323
 
 
324
func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) {
 
325
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
326
        c.Assert(err, gc.IsNil)
 
327
 
 
328
        _, err = apiMachine.WatchContainers(instance.NONE)
 
329
        c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`)
 
330
 
 
331
        _, err = apiMachine.WatchContainers("")
 
332
        c.Assert(err, gc.ErrorMatches, "container type must be specified")
 
333
}
 
334
 
 
335
func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) {
 
336
        w, err := s.provisioner.WatchEnvironMachines()
 
337
        c.Assert(err, gc.IsNil)
 
338
        defer statetesting.AssertStop(c, w)
 
339
        wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
 
340
 
 
341
        // Initial event.
 
342
        wc.AssertChange(s.machine.Id())
 
343
 
 
344
        // Add another 2 machines make sure they are detected.
 
345
        otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
 
346
        c.Assert(err, gc.IsNil)
 
347
        otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
 
348
        c.Assert(err, gc.IsNil)
 
349
        wc.AssertChange("1", "2")
 
350
 
 
351
        // Change the lifecycle of last machine.
 
352
        err = otherMachine.EnsureDead()
 
353
        c.Assert(err, gc.IsNil)
 
354
        wc.AssertChange("2")
 
355
 
 
356
        // Add a container and make sure it's not detected.
 
357
        template := state.MachineTemplate{
 
358
                Series: "quantal",
 
359
                Jobs:   []state.MachineJob{state.JobHostUnits},
 
360
        }
 
361
        _, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
 
362
        c.Assert(err, gc.IsNil)
 
363
        wc.AssertNoChange()
 
364
 
 
365
        statetesting.AssertStop(c, w)
 
366
        wc.AssertClosed()
 
367
}
 
368
 
 
369
func (s *provisionerSuite) TestStateAddresses(c *gc.C) {
 
370
        err := s.machine.SetAddresses([]instance.Address{
 
371
                instance.NewAddress("0.1.2.3"),
 
372
        })
 
373
        c.Assert(err, gc.IsNil)
 
374
 
 
375
        stateAddresses, err := s.State.Addresses()
 
376
        c.Assert(err, gc.IsNil)
 
377
 
 
378
        addresses, err := s.provisioner.StateAddresses()
 
379
        c.Assert(err, gc.IsNil)
 
380
        c.Assert(addresses, gc.DeepEquals, stateAddresses)
 
381
}
 
382
 
 
383
func (s *provisionerSuite) TestContainerConfig(c *gc.C) {
 
384
        result, err := s.provisioner.ContainerConfig()
 
385
        c.Assert(err, gc.IsNil)
 
386
        c.Assert(result.ProviderType, gc.Equals, "dummy")
 
387
        c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys)
 
388
        c.Assert(result.SSLHostnameVerification, jc.IsTrue)
 
389
}
 
390
 
 
391
func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) {
 
392
        tools, err := s.provisioner.Tools("42")
 
393
        c.Assert(err, gc.ErrorMatches, "permission denied")
 
394
        c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
 
395
        c.Assert(tools, gc.IsNil)
 
396
}
 
397
 
 
398
func (s *provisionerSuite) TestTools(c *gc.C) {
 
399
        cur := version.Current
 
400
        curTools := &tools.Tools{Version: cur, URL: ""}
 
401
        curTools.Version.Minor++
 
402
        s.machine.SetAgentVersion(cur)
 
403
        // Provisioner.Tools returns the *desired* set of tools, not the
 
404
        // currently running set. We want to be upgraded to cur.Version
 
405
        stateTools, err := s.provisioner.Tools(s.machine.Tag())
 
406
        c.Assert(err, gc.IsNil)
 
407
        c.Assert(stateTools.Version, gc.Equals, cur)
 
408
        c.Assert(stateTools.URL, gc.Not(gc.Equals), "")
 
409
}
 
410
 
 
411
func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) {
 
412
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
413
        c.Assert(err, gc.IsNil)
 
414
        err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM)
 
415
        c.Assert(err, gc.IsNil)
 
416
 
 
417
        err = s.machine.Refresh()
 
418
        c.Assert(err, gc.IsNil)
 
419
        containers, ok := s.machine.SupportedContainers()
 
420
        c.Assert(ok, jc.IsTrue)
 
421
        c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
 
422
}
 
423
 
 
424
func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) {
 
425
        apiMachine, err := s.provisioner.Machine(s.machine.Tag())
 
426
        c.Assert(err, gc.IsNil)
 
427
        err = apiMachine.SupportsNoContainers()
 
428
        c.Assert(err, gc.IsNil)
 
429
 
 
430
        err = s.machine.Refresh()
 
431
        c.Assert(err, gc.IsNil)
 
432
        containers, ok := s.machine.SupportedContainers()
 
433
        c.Assert(ok, jc.IsTrue)
 
434
        c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
 
435
}