github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/state/apiserver/firewaller/firewaller_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package firewaller_test 5 6 import ( 7 stdtesting "testing" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 gc "launchpad.net/gocheck" 12 13 "github.com/juju/juju/instance" 14 "github.com/juju/juju/juju/testing" 15 "github.com/juju/juju/network" 16 "github.com/juju/juju/state" 17 "github.com/juju/juju/state/api/params" 18 "github.com/juju/juju/state/apiserver/common" 19 commontesting "github.com/juju/juju/state/apiserver/common/testing" 20 "github.com/juju/juju/state/apiserver/firewaller" 21 apiservertesting "github.com/juju/juju/state/apiserver/testing" 22 statetesting "github.com/juju/juju/state/testing" 23 coretesting "github.com/juju/juju/testing" 24 ) 25 26 func Test(t *stdtesting.T) { 27 coretesting.MgoTestPackage(t) 28 } 29 30 type firewallerSuite struct { 31 testing.JujuConnSuite 32 *commontesting.EnvironWatcherTest 33 34 machines []*state.Machine 35 service *state.Service 36 charm *state.Charm 37 units []*state.Unit 38 39 authorizer apiservertesting.FakeAuthorizer 40 resources *common.Resources 41 firewaller *firewaller.FirewallerAPI 42 } 43 44 var _ = gc.Suite(&firewallerSuite{}) 45 46 func (s *firewallerSuite) SetUpTest(c *gc.C) { 47 s.JujuConnSuite.SetUpTest(c) 48 49 // Reset previous machines and units (if any) and create 3 50 // machines for the tests. 51 s.machines = nil 52 s.units = nil 53 // Note that the specific machine ids allocated are assumed 54 // to be numerically consecutive from zero. 55 for i := 0; i <= 2; i++ { 56 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 57 c.Check(err, gc.IsNil) 58 s.machines = append(s.machines, machine) 59 } 60 // Create a service and three units for these machines. 61 s.charm = s.AddTestingCharm(c, "wordpress") 62 s.service = s.AddTestingService(c, "wordpress", s.charm) 63 // Add the rest of the units and assign them. 64 for i := 0; i <= 2; i++ { 65 unit, err := s.service.AddUnit() 66 c.Check(err, gc.IsNil) 67 err = unit.AssignToMachine(s.machines[i]) 68 c.Check(err, gc.IsNil) 69 s.units = append(s.units, unit) 70 } 71 72 // Create a FakeAuthorizer so we can check permissions, 73 // set up assuming we logged in as the environment manager. 74 s.authorizer = apiservertesting.FakeAuthorizer{ 75 LoggedIn: true, 76 EnvironManager: true, 77 } 78 79 // Create the resource registry separately to track invocations to 80 // Register. 81 s.resources = common.NewResources() 82 83 // Create a firewaller API for the machine. 84 firewallerAPI, err := firewaller.NewFirewallerAPI( 85 s.State, 86 s.resources, 87 s.authorizer, 88 ) 89 c.Assert(err, gc.IsNil) 90 s.firewaller = firewallerAPI 91 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.firewaller, s.State, s.resources, commontesting.HasSecrets) 92 } 93 94 func (s *firewallerSuite) TestFirewallerFailsWithNonEnvironManagerUser(c *gc.C) { 95 anAuthorizer := s.authorizer 96 anAuthorizer.MachineAgent = true 97 anAuthorizer.EnvironManager = false 98 aFirewaller, err := firewaller.NewFirewallerAPI(s.State, s.resources, anAuthorizer) 99 c.Assert(err, gc.NotNil) 100 c.Assert(err, gc.ErrorMatches, "permission denied") 101 c.Assert(aFirewaller, gc.IsNil) 102 } 103 104 func (s *firewallerSuite) TestLife(c *gc.C) { 105 // Unassign unit 1 from its machine, so we can change its life cycle. 106 err := s.units[1].UnassignFromMachine() 107 c.Assert(err, gc.IsNil) 108 109 err = s.machines[1].EnsureDead() 110 c.Assert(err, gc.IsNil) 111 s.assertLife(c, 0, state.Alive) 112 s.assertLife(c, 1, state.Dead) 113 s.assertLife(c, 2, state.Alive) 114 115 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 116 {Tag: s.machines[0].Tag()}, 117 {Tag: s.machines[1].Tag()}, 118 {Tag: s.machines[2].Tag()}, 119 }}) 120 result, err := s.firewaller.Life(args) 121 c.Assert(err, gc.IsNil) 122 c.Assert(result, jc.DeepEquals, params.LifeResults{ 123 Results: []params.LifeResult{ 124 {Life: "alive"}, 125 {Life: "dead"}, 126 {Life: "alive"}, 127 {Error: apiservertesting.NotFoundError("machine 42")}, 128 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 129 {Error: apiservertesting.NotFoundError(`service "bar"`)}, 130 {Error: apiservertesting.ErrUnauthorized}, 131 {Error: apiservertesting.ErrUnauthorized}, 132 {Error: apiservertesting.ErrUnauthorized}, 133 }, 134 }) 135 136 // Remove a machine and make sure it's detected. 137 err = s.machines[1].Remove() 138 c.Assert(err, gc.IsNil) 139 err = s.machines[1].Refresh() 140 c.Assert(err, jc.Satisfies, errors.IsNotFound) 141 142 args = params.Entities{ 143 Entities: []params.Entity{ 144 {Tag: s.machines[1].Tag()}, 145 }, 146 } 147 result, err = s.firewaller.Life(args) 148 c.Assert(err, gc.IsNil) 149 c.Assert(result, jc.DeepEquals, params.LifeResults{ 150 Results: []params.LifeResult{ 151 {Error: apiservertesting.NotFoundError("machine 1")}, 152 }, 153 }) 154 } 155 156 func (s *firewallerSuite) TestInstanceId(c *gc.C) { 157 // Provision 2 machines first. 158 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) 159 c.Assert(err, gc.IsNil) 160 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 161 err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) 162 c.Assert(err, gc.IsNil) 163 164 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 165 {Tag: s.machines[0].Tag()}, 166 {Tag: s.machines[1].Tag()}, 167 {Tag: s.machines[2].Tag()}, 168 {Tag: s.service.Tag()}, 169 {Tag: s.units[2].Tag()}, 170 }}) 171 result, err := s.firewaller.InstanceId(args) 172 c.Assert(err, gc.IsNil) 173 c.Assert(result, jc.DeepEquals, params.StringResults{ 174 Results: []params.StringResult{ 175 {Result: "i-am"}, 176 {Result: "i-am-not"}, 177 {Error: apiservertesting.NotProvisionedError("2")}, 178 {Error: apiservertesting.ErrUnauthorized}, 179 {Error: apiservertesting.ErrUnauthorized}, 180 {Error: apiservertesting.NotFoundError("machine 42")}, 181 {Error: apiservertesting.ErrUnauthorized}, 182 {Error: apiservertesting.ErrUnauthorized}, 183 {Error: apiservertesting.ErrUnauthorized}, 184 {Error: apiservertesting.ErrUnauthorized}, 185 {Error: apiservertesting.ErrUnauthorized}, 186 }, 187 }) 188 } 189 190 func (s *firewallerSuite) TestWatchEnvironMachines(c *gc.C) { 191 c.Assert(s.resources.Count(), gc.Equals, 0) 192 193 got, err := s.firewaller.WatchEnvironMachines() 194 c.Assert(err, gc.IsNil) 195 want := params.StringsWatchResult{ 196 StringsWatcherId: "1", 197 Changes: []string{"0", "1", "2"}, 198 } 199 c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) 200 c.Assert(got.Changes, jc.SameContents, want.Changes) 201 202 // Verify the resources were registered and stop them when done. 203 c.Assert(s.resources.Count(), gc.Equals, 1) 204 resource := s.resources.Get("1") 205 defer statetesting.AssertStop(c, resource) 206 207 // Check that the Watch has consumed the initial event ("returned" 208 // in the Watch call) 209 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 210 wc.AssertNoChange() 211 } 212 213 func (s *firewallerSuite) TestWatch(c *gc.C) { 214 c.Assert(s.resources.Count(), gc.Equals, 0) 215 216 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 217 {Tag: s.machines[0].Tag()}, 218 {Tag: s.service.Tag()}, 219 {Tag: s.units[0].Tag()}, 220 }}) 221 result, err := s.firewaller.Watch(args) 222 c.Assert(err, gc.IsNil) 223 c.Assert(result, jc.DeepEquals, params.NotifyWatchResults{ 224 Results: []params.NotifyWatchResult{ 225 {Error: apiservertesting.ErrUnauthorized}, 226 {NotifyWatcherId: "1"}, 227 {NotifyWatcherId: "2"}, 228 {Error: apiservertesting.ErrUnauthorized}, 229 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 230 {Error: apiservertesting.NotFoundError(`service "bar"`)}, 231 {Error: apiservertesting.ErrUnauthorized}, 232 {Error: apiservertesting.ErrUnauthorized}, 233 {Error: apiservertesting.ErrUnauthorized}, 234 }, 235 }) 236 237 // Verify the resources were registered and stop when done. 238 c.Assert(s.resources.Count(), gc.Equals, 2) 239 c.Assert(result.Results[1].NotifyWatcherId, gc.Equals, "1") 240 watcher1 := s.resources.Get("1") 241 defer statetesting.AssertStop(c, watcher1) 242 c.Assert(result.Results[2].NotifyWatcherId, gc.Equals, "2") 243 watcher2 := s.resources.Get("2") 244 defer statetesting.AssertStop(c, watcher2) 245 246 // Check that the Watch has consumed the initial event ("returned" in 247 // the Watch call) 248 wc1 := statetesting.NewNotifyWatcherC(c, s.State, watcher1.(state.NotifyWatcher)) 249 wc1.AssertNoChange() 250 wc2 := statetesting.NewNotifyWatcherC(c, s.State, watcher2.(state.NotifyWatcher)) 251 wc2.AssertNoChange() 252 } 253 254 func (s *firewallerSuite) TestWatchUnits(c *gc.C) { 255 c.Assert(s.resources.Count(), gc.Equals, 0) 256 257 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 258 {Tag: s.machines[0].Tag()}, 259 {Tag: s.service.Tag()}, 260 {Tag: s.units[0].Tag()}, 261 }}) 262 result, err := s.firewaller.WatchUnits(args) 263 c.Assert(err, gc.IsNil) 264 c.Assert(result, jc.DeepEquals, params.StringsWatchResults{ 265 Results: []params.StringsWatchResult{ 266 {Changes: []string{"wordpress/0"}, StringsWatcherId: "1"}, 267 {Error: apiservertesting.ErrUnauthorized}, 268 {Error: apiservertesting.ErrUnauthorized}, 269 {Error: apiservertesting.NotFoundError("machine 42")}, 270 {Error: apiservertesting.ErrUnauthorized}, 271 {Error: apiservertesting.ErrUnauthorized}, 272 {Error: apiservertesting.ErrUnauthorized}, 273 {Error: apiservertesting.ErrUnauthorized}, 274 {Error: apiservertesting.ErrUnauthorized}, 275 }, 276 }) 277 278 // Verify the resource was registered and stop when done 279 c.Assert(s.resources.Count(), gc.Equals, 1) 280 c.Assert(result.Results[0].StringsWatcherId, gc.Equals, "1") 281 resource := s.resources.Get("1") 282 defer statetesting.AssertStop(c, resource) 283 284 // Check that the Watch has consumed the initial event ("returned" in 285 // the Watch call) 286 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 287 wc.AssertNoChange() 288 } 289 290 func (s *firewallerSuite) TestGetExposed(c *gc.C) { 291 // Set the service to exposed first. 292 err := s.service.SetExposed() 293 c.Assert(err, gc.IsNil) 294 295 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 296 {Tag: s.service.Tag()}, 297 }}) 298 result, err := s.firewaller.GetExposed(args) 299 c.Assert(err, gc.IsNil) 300 c.Assert(result, jc.DeepEquals, params.BoolResults{ 301 Results: []params.BoolResult{ 302 {Result: true}, 303 {Error: apiservertesting.ErrUnauthorized}, 304 {Error: apiservertesting.ErrUnauthorized}, 305 {Error: apiservertesting.NotFoundError(`service "bar"`)}, 306 {Error: apiservertesting.ErrUnauthorized}, 307 {Error: apiservertesting.ErrUnauthorized}, 308 {Error: apiservertesting.ErrUnauthorized}, 309 }, 310 }) 311 312 // Now reset the exposed flag for the service and check again. 313 err = s.service.ClearExposed() 314 c.Assert(err, gc.IsNil) 315 316 args = params.Entities{Entities: []params.Entity{ 317 {Tag: s.service.Tag()}, 318 }} 319 result, err = s.firewaller.GetExposed(args) 320 c.Assert(err, gc.IsNil) 321 c.Assert(result, jc.DeepEquals, params.BoolResults{ 322 Results: []params.BoolResult{ 323 {Result: false}, 324 }, 325 }) 326 } 327 328 func (s *firewallerSuite) TestOpenedPorts(c *gc.C) { 329 // Open some ports on two of the units. 330 err := s.units[0].OpenPort("foo", 1234) 331 c.Assert(err, gc.IsNil) 332 err = s.units[0].OpenPort("bar", 4321) 333 c.Assert(err, gc.IsNil) 334 err = s.units[2].OpenPort("baz", 1111) 335 c.Assert(err, gc.IsNil) 336 337 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 338 {Tag: s.units[0].Tag()}, 339 {Tag: s.units[1].Tag()}, 340 {Tag: s.units[2].Tag()}, 341 }}) 342 result, err := s.firewaller.OpenedPorts(args) 343 c.Assert(err, gc.IsNil) 344 c.Assert(result, jc.DeepEquals, params.PortsResults{ 345 Results: []params.PortsResult{ 346 {Ports: []network.Port{{"bar", 4321}, {"foo", 1234}}}, 347 {Ports: []network.Port{}}, 348 {Ports: []network.Port{{"baz", 1111}}}, 349 {Error: apiservertesting.ErrUnauthorized}, 350 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 351 {Error: apiservertesting.ErrUnauthorized}, 352 {Error: apiservertesting.ErrUnauthorized}, 353 {Error: apiservertesting.ErrUnauthorized}, 354 {Error: apiservertesting.ErrUnauthorized}, 355 }, 356 }) 357 358 // Now close unit 2's port and check again. 359 err = s.units[2].ClosePort("baz", 1111) 360 c.Assert(err, gc.IsNil) 361 362 args = params.Entities{Entities: []params.Entity{ 363 {Tag: s.units[2].Tag()}, 364 }} 365 result, err = s.firewaller.OpenedPorts(args) 366 c.Assert(err, gc.IsNil) 367 c.Assert(result, jc.DeepEquals, params.PortsResults{ 368 Results: []params.PortsResult{ 369 {Ports: []network.Port{}}, 370 }, 371 }) 372 } 373 374 func (s *firewallerSuite) TestGetAssignedMachine(c *gc.C) { 375 // Unassign a unit first. 376 err := s.units[2].UnassignFromMachine() 377 c.Assert(err, gc.IsNil) 378 379 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 380 {Tag: s.units[0].Tag()}, 381 {Tag: s.units[1].Tag()}, 382 {Tag: s.units[2].Tag()}, 383 }}) 384 result, err := s.firewaller.GetAssignedMachine(args) 385 c.Assert(err, gc.IsNil) 386 c.Assert(result, jc.DeepEquals, params.StringResults{ 387 Results: []params.StringResult{ 388 {Result: s.machines[0].Tag()}, 389 {Result: s.machines[1].Tag()}, 390 {Error: apiservertesting.NotAssignedError("wordpress/2")}, 391 {Error: apiservertesting.ErrUnauthorized}, 392 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 393 {Error: apiservertesting.ErrUnauthorized}, 394 {Error: apiservertesting.ErrUnauthorized}, 395 {Error: apiservertesting.ErrUnauthorized}, 396 {Error: apiservertesting.ErrUnauthorized}, 397 }, 398 }) 399 400 // Now reset assign unit 2 again and check. 401 err = s.units[2].AssignToMachine(s.machines[0]) 402 c.Assert(err, gc.IsNil) 403 404 args = params.Entities{Entities: []params.Entity{ 405 {Tag: s.units[2].Tag()}, 406 }} 407 result, err = s.firewaller.GetAssignedMachine(args) 408 c.Assert(err, gc.IsNil) 409 c.Assert(result, jc.DeepEquals, params.StringResults{ 410 Results: []params.StringResult{ 411 {Result: s.machines[0].Tag()}, 412 }, 413 }) 414 } 415 416 func (s *firewallerSuite) assertLife(c *gc.C, index int, expectLife state.Life) { 417 err := s.machines[index].Refresh() 418 c.Assert(err, gc.IsNil) 419 c.Assert(s.machines[index].Life(), gc.Equals, expectLife) 420 } 421 422 var commonFakeEntities = []params.Entity{ 423 {Tag: "machine-42"}, 424 {Tag: "unit-foo-0"}, 425 {Tag: "service-bar"}, 426 {Tag: "user-foo"}, 427 {Tag: "foo-bar"}, 428 {Tag: ""}, 429 } 430 431 func addFakeEntities(actual params.Entities) params.Entities { 432 for _, entity := range commonFakeEntities { 433 actual.Entities = append(actual.Entities, entity) 434 } 435 return actual 436 }