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