1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
4
package firewaller_test
9
gc "launchpad.net/gocheck"
11
"launchpad.net/juju-core/errors"
12
"launchpad.net/juju-core/instance"
13
"launchpad.net/juju-core/juju/testing"
14
"launchpad.net/juju-core/state"
15
"launchpad.net/juju-core/state/api/params"
16
"launchpad.net/juju-core/state/apiserver/common"
17
commontesting "launchpad.net/juju-core/state/apiserver/common/testing"
18
"launchpad.net/juju-core/state/apiserver/firewaller"
19
apiservertesting "launchpad.net/juju-core/state/apiserver/testing"
20
statetesting "launchpad.net/juju-core/state/testing"
21
coretesting "launchpad.net/juju-core/testing"
22
jc "launchpad.net/juju-core/testing/checkers"
25
func Test(t *stdtesting.T) {
26
coretesting.MgoTestPackage(t)
29
type firewallerSuite struct {
31
*commontesting.EnvironWatcherTest
33
machines []*state.Machine
34
service *state.Service
38
authorizer apiservertesting.FakeAuthorizer
39
resources *common.Resources
40
firewaller *firewaller.FirewallerAPI
43
var _ = gc.Suite(&firewallerSuite{})
45
func (s *firewallerSuite) SetUpTest(c *gc.C) {
46
s.JujuConnSuite.SetUpTest(c)
48
// Reset previous machines and units (if any) and create 3
49
// machines for the tests.
52
// Note that the specific machine ids allocated are assumed
53
// to be numerically consecutive from zero.
54
for i := 0; i <= 2; i++ {
55
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
56
c.Check(err, gc.IsNil)
57
s.machines = append(s.machines, machine)
59
// Create a service and three units for these machines.
60
s.charm = s.AddTestingCharm(c, "wordpress")
61
s.service = s.AddTestingService(c, "wordpress", s.charm)
62
// Add the rest of the units and assign them.
63
for i := 0; i <= 2; i++ {
64
unit, err := s.service.AddUnit()
65
c.Check(err, gc.IsNil)
66
err = unit.AssignToMachine(s.machines[i])
67
c.Check(err, gc.IsNil)
68
s.units = append(s.units, unit)
71
// Create a FakeAuthorizer so we can check permissions,
72
// set up assuming we logged in as the environment manager.
73
s.authorizer = apiservertesting.FakeAuthorizer{
78
// Create the resource registry separately to track invocations to
80
s.resources = common.NewResources()
82
// Create a firewaller API for the machine.
83
firewallerAPI, err := firewaller.NewFirewallerAPI(
88
c.Assert(err, gc.IsNil)
89
s.firewaller = firewallerAPI
90
s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.firewaller, s.State, s.resources, commontesting.HasSecrets)
93
func (s *firewallerSuite) TestFirewallerFailsWithNonEnvironManagerUser(c *gc.C) {
94
anAuthorizer := s.authorizer
95
anAuthorizer.MachineAgent = true
96
anAuthorizer.EnvironManager = false
97
aFirewaller, err := firewaller.NewFirewallerAPI(s.State, s.resources, anAuthorizer)
98
c.Assert(err, gc.NotNil)
99
c.Assert(err, gc.ErrorMatches, "permission denied")
100
c.Assert(aFirewaller, gc.IsNil)
103
func (s *firewallerSuite) TestLife(c *gc.C) {
104
// Unassign unit 1 from its machine, so we can change its life cycle.
105
err := s.units[1].UnassignFromMachine()
106
c.Assert(err, gc.IsNil)
108
err = s.machines[1].EnsureDead()
109
c.Assert(err, gc.IsNil)
110
s.assertLife(c, 0, state.Alive)
111
s.assertLife(c, 1, state.Dead)
112
s.assertLife(c, 2, state.Alive)
114
args := addFakeEntities(params.Entities{Entities: []params.Entity{
115
{Tag: s.machines[0].Tag()},
116
{Tag: s.machines[1].Tag()},
117
{Tag: s.machines[2].Tag()},
119
result, err := s.firewaller.Life(args)
120
c.Assert(err, gc.IsNil)
121
c.Assert(result, jc.DeepEquals, params.LifeResults{
122
Results: []params.LifeResult{
126
{Error: apiservertesting.NotFoundError("machine 42")},
127
{Error: apiservertesting.NotFoundError(`unit "foo/0"`)},
128
{Error: apiservertesting.NotFoundError(`service "bar"`)},
129
{Error: apiservertesting.ErrUnauthorized},
130
{Error: apiservertesting.ErrUnauthorized},
131
{Error: apiservertesting.ErrUnauthorized},
135
// Remove a machine and make sure it's detected.
136
err = s.machines[1].Remove()
137
c.Assert(err, gc.IsNil)
138
err = s.machines[1].Refresh()
139
c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
141
args = params.Entities{
142
Entities: []params.Entity{
143
{Tag: s.machines[1].Tag()},
146
result, err = s.firewaller.Life(args)
147
c.Assert(err, gc.IsNil)
148
c.Assert(result, jc.DeepEquals, params.LifeResults{
149
Results: []params.LifeResult{
150
{Error: apiservertesting.NotFoundError("machine 1")},
155
func (s *firewallerSuite) TestInstanceId(c *gc.C) {
156
// Provision 2 machines first.
157
err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil)
158
c.Assert(err, gc.IsNil)
159
hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
160
err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars)
161
c.Assert(err, gc.IsNil)
163
args := addFakeEntities(params.Entities{Entities: []params.Entity{
164
{Tag: s.machines[0].Tag()},
165
{Tag: s.machines[1].Tag()},
166
{Tag: s.machines[2].Tag()},
167
{Tag: s.service.Tag()},
168
{Tag: s.units[2].Tag()},
170
result, err := s.firewaller.InstanceId(args)
171
c.Assert(err, gc.IsNil)
172
c.Assert(result, jc.DeepEquals, params.StringResults{
173
Results: []params.StringResult{
175
{Result: "i-am-not"},
176
{Error: apiservertesting.NotProvisionedError("2")},
177
{Error: apiservertesting.ErrUnauthorized},
178
{Error: apiservertesting.ErrUnauthorized},
179
{Error: apiservertesting.NotFoundError("machine 42")},
180
{Error: apiservertesting.ErrUnauthorized},
181
{Error: apiservertesting.ErrUnauthorized},
182
{Error: apiservertesting.ErrUnauthorized},
183
{Error: apiservertesting.ErrUnauthorized},
184
{Error: apiservertesting.ErrUnauthorized},
189
func (s *firewallerSuite) TestWatchEnvironMachines(c *gc.C) {
190
c.Assert(s.resources.Count(), gc.Equals, 0)
192
result, err := s.firewaller.WatchEnvironMachines()
193
c.Assert(err, gc.IsNil)
194
c.Assert(result, jc.DeepEquals, params.StringsWatchResult{
195
StringsWatcherId: "1",
196
Changes: []string{"0", "1", "2"},
199
// Verify the resources were registered and stop them when done.
200
c.Assert(s.resources.Count(), gc.Equals, 1)
201
resource := s.resources.Get("1")
202
defer statetesting.AssertStop(c, resource)
204
// Check that the Watch has consumed the initial event ("returned"
205
// in the Watch call)
206
wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
210
func (s *firewallerSuite) TestWatch(c *gc.C) {
211
c.Assert(s.resources.Count(), gc.Equals, 0)
213
args := addFakeEntities(params.Entities{Entities: []params.Entity{
214
{Tag: s.machines[0].Tag()},
215
{Tag: s.service.Tag()},
216
{Tag: s.units[0].Tag()},
218
result, err := s.firewaller.Watch(args)
219
c.Assert(err, gc.IsNil)
220
c.Assert(result, jc.DeepEquals, params.NotifyWatchResults{
221
Results: []params.NotifyWatchResult{
222
{Error: apiservertesting.ErrUnauthorized},
223
{NotifyWatcherId: "1"},
224
{NotifyWatcherId: "2"},
225
{Error: apiservertesting.ErrUnauthorized},
226
{Error: apiservertesting.NotFoundError(`unit "foo/0"`)},
227
{Error: apiservertesting.NotFoundError(`service "bar"`)},
228
{Error: apiservertesting.ErrUnauthorized},
229
{Error: apiservertesting.ErrUnauthorized},
230
{Error: apiservertesting.ErrUnauthorized},
234
// Verify the resources were registered and stop when done.
235
c.Assert(s.resources.Count(), gc.Equals, 2)
236
c.Assert(result.Results[1].NotifyWatcherId, gc.Equals, "1")
237
watcher1 := s.resources.Get("1")
238
defer statetesting.AssertStop(c, watcher1)
239
c.Assert(result.Results[2].NotifyWatcherId, gc.Equals, "2")
240
watcher2 := s.resources.Get("2")
241
defer statetesting.AssertStop(c, watcher2)
243
// Check that the Watch has consumed the initial event ("returned" in
245
wc1 := statetesting.NewNotifyWatcherC(c, s.State, watcher1.(state.NotifyWatcher))
247
wc2 := statetesting.NewNotifyWatcherC(c, s.State, watcher2.(state.NotifyWatcher))
251
func (s *firewallerSuite) TestWatchUnits(c *gc.C) {
252
c.Assert(s.resources.Count(), gc.Equals, 0)
254
args := addFakeEntities(params.Entities{Entities: []params.Entity{
255
{Tag: s.machines[0].Tag()},
256
{Tag: s.service.Tag()},
257
{Tag: s.units[0].Tag()},
259
result, err := s.firewaller.WatchUnits(args)
260
c.Assert(err, gc.IsNil)
261
c.Assert(result, jc.DeepEquals, params.StringsWatchResults{
262
Results: []params.StringsWatchResult{
263
{Changes: []string{"wordpress/0"}, StringsWatcherId: "1"},
264
{Error: apiservertesting.ErrUnauthorized},
265
{Error: apiservertesting.ErrUnauthorized},
266
{Error: apiservertesting.NotFoundError("machine 42")},
267
{Error: apiservertesting.ErrUnauthorized},
268
{Error: apiservertesting.ErrUnauthorized},
269
{Error: apiservertesting.ErrUnauthorized},
270
{Error: apiservertesting.ErrUnauthorized},
271
{Error: apiservertesting.ErrUnauthorized},
275
// Verify the resource was registered and stop when done
276
c.Assert(s.resources.Count(), gc.Equals, 1)
277
c.Assert(result.Results[0].StringsWatcherId, gc.Equals, "1")
278
resource := s.resources.Get("1")
279
defer statetesting.AssertStop(c, resource)
281
// Check that the Watch has consumed the initial event ("returned" in
283
wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
287
func (s *firewallerSuite) TestGetExposed(c *gc.C) {
288
// Set the service to exposed first.
289
err := s.service.SetExposed()
290
c.Assert(err, gc.IsNil)
292
args := addFakeEntities(params.Entities{Entities: []params.Entity{
293
{Tag: s.service.Tag()},
295
result, err := s.firewaller.GetExposed(args)
296
c.Assert(err, gc.IsNil)
297
c.Assert(result, jc.DeepEquals, params.BoolResults{
298
Results: []params.BoolResult{
300
{Error: apiservertesting.ErrUnauthorized},
301
{Error: apiservertesting.ErrUnauthorized},
302
{Error: apiservertesting.NotFoundError(`service "bar"`)},
303
{Error: apiservertesting.ErrUnauthorized},
304
{Error: apiservertesting.ErrUnauthorized},
305
{Error: apiservertesting.ErrUnauthorized},
309
// Now reset the exposed flag for the service and check again.
310
err = s.service.ClearExposed()
311
c.Assert(err, gc.IsNil)
313
args = params.Entities{Entities: []params.Entity{
314
{Tag: s.service.Tag()},
316
result, err = s.firewaller.GetExposed(args)
317
c.Assert(err, gc.IsNil)
318
c.Assert(result, jc.DeepEquals, params.BoolResults{
319
Results: []params.BoolResult{
325
func (s *firewallerSuite) TestOpenedPorts(c *gc.C) {
326
// Open some ports on two of the units.
327
err := s.units[0].OpenPort("foo", 1234)
328
c.Assert(err, gc.IsNil)
329
err = s.units[0].OpenPort("bar", 4321)
330
c.Assert(err, gc.IsNil)
331
err = s.units[2].OpenPort("baz", 1111)
332
c.Assert(err, gc.IsNil)
334
args := addFakeEntities(params.Entities{Entities: []params.Entity{
335
{Tag: s.units[0].Tag()},
336
{Tag: s.units[1].Tag()},
337
{Tag: s.units[2].Tag()},
339
result, err := s.firewaller.OpenedPorts(args)
340
c.Assert(err, gc.IsNil)
341
c.Assert(result, jc.DeepEquals, params.PortsResults{
342
Results: []params.PortsResult{
343
{Ports: []instance.Port{{"bar", 4321}, {"foo", 1234}}},
344
{Ports: []instance.Port{}},
345
{Ports: []instance.Port{{"baz", 1111}}},
346
{Error: apiservertesting.ErrUnauthorized},
347
{Error: apiservertesting.NotFoundError(`unit "foo/0"`)},
348
{Error: apiservertesting.ErrUnauthorized},
349
{Error: apiservertesting.ErrUnauthorized},
350
{Error: apiservertesting.ErrUnauthorized},
351
{Error: apiservertesting.ErrUnauthorized},
355
// Now close unit 2's port and check again.
356
err = s.units[2].ClosePort("baz", 1111)
357
c.Assert(err, gc.IsNil)
359
args = params.Entities{Entities: []params.Entity{
360
{Tag: s.units[2].Tag()},
362
result, err = s.firewaller.OpenedPorts(args)
363
c.Assert(err, gc.IsNil)
364
c.Assert(result, jc.DeepEquals, params.PortsResults{
365
Results: []params.PortsResult{
366
{Ports: []instance.Port{}},
371
func (s *firewallerSuite) TestGetAssignedMachine(c *gc.C) {
372
// Unassign a unit first.
373
err := s.units[2].UnassignFromMachine()
374
c.Assert(err, gc.IsNil)
376
args := addFakeEntities(params.Entities{Entities: []params.Entity{
377
{Tag: s.units[0].Tag()},
378
{Tag: s.units[1].Tag()},
379
{Tag: s.units[2].Tag()},
381
result, err := s.firewaller.GetAssignedMachine(args)
382
c.Assert(err, gc.IsNil)
383
c.Assert(result, jc.DeepEquals, params.StringResults{
384
Results: []params.StringResult{
385
{Result: s.machines[0].Tag()},
386
{Result: s.machines[1].Tag()},
387
{Error: apiservertesting.NotAssignedError("wordpress/2")},
388
{Error: apiservertesting.ErrUnauthorized},
389
{Error: apiservertesting.NotFoundError(`unit "foo/0"`)},
390
{Error: apiservertesting.ErrUnauthorized},
391
{Error: apiservertesting.ErrUnauthorized},
392
{Error: apiservertesting.ErrUnauthorized},
393
{Error: apiservertesting.ErrUnauthorized},
397
// Now reset assign unit 2 again and check.
398
err = s.units[2].AssignToMachine(s.machines[0])
399
c.Assert(err, gc.IsNil)
401
args = params.Entities{Entities: []params.Entity{
402
{Tag: s.units[2].Tag()},
404
result, err = s.firewaller.GetAssignedMachine(args)
405
c.Assert(err, gc.IsNil)
406
c.Assert(result, jc.DeepEquals, params.StringResults{
407
Results: []params.StringResult{
408
{Result: s.machines[0].Tag()},
413
func (s *firewallerSuite) assertLife(c *gc.C, index int, expectLife state.Life) {
414
err := s.machines[index].Refresh()
415
c.Assert(err, gc.IsNil)
416
c.Assert(s.machines[index].Life(), gc.Equals, expectLife)
419
var commonFakeEntities = []params.Entity{
422
{Tag: "service-bar"},
428
func addFakeEntities(actual params.Entities) params.Entities {
429
for _, entity := range commonFakeEntities {
430
actual.Entities = append(actual.Entities, entity)