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

1 by Casey Marshall
Source distribution of launchpad.net/juju-core created 20140327105939
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
}