github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/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 gc "launchpad.net/gocheck" 10 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" 23 ) 24 25 func Test(t *stdtesting.T) { 26 coretesting.MgoTestPackage(t) 27 } 28 29 type firewallerSuite struct { 30 testing.JujuConnSuite 31 *commontesting.EnvironWatcherTest 32 33 machines []*state.Machine 34 service *state.Service 35 charm *state.Charm 36 units []*state.Unit 37 38 authorizer apiservertesting.FakeAuthorizer 39 resources *common.Resources 40 firewaller *firewaller.FirewallerAPI 41 } 42 43 var _ = gc.Suite(&firewallerSuite{}) 44 45 func (s *firewallerSuite) SetUpTest(c *gc.C) { 46 s.JujuConnSuite.SetUpTest(c) 47 48 // Reset previous machines and units (if any) and create 3 49 // machines for the tests. 50 s.machines = nil 51 s.units = nil 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) 58 } 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) 69 } 70 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{ 74 LoggedIn: true, 75 EnvironManager: true, 76 } 77 78 // Create the resource registry separately to track invocations to 79 // Register. 80 s.resources = common.NewResources() 81 82 // Create a firewaller API for the machine. 83 firewallerAPI, err := firewaller.NewFirewallerAPI( 84 s.State, 85 s.resources, 86 s.authorizer, 87 ) 88 c.Assert(err, gc.IsNil) 89 s.firewaller = firewallerAPI 90 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.firewaller, s.State, s.resources, commontesting.HasSecrets) 91 } 92 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) 101 } 102 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) 107 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) 113 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()}, 118 }}) 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{ 123 {Life: "alive"}, 124 {Life: "dead"}, 125 {Life: "alive"}, 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}, 132 }, 133 }) 134 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) 140 141 args = params.Entities{ 142 Entities: []params.Entity{ 143 {Tag: s.machines[1].Tag()}, 144 }, 145 } 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")}, 151 }, 152 }) 153 } 154 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) 162 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()}, 169 }}) 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{ 174 {Result: "i-am"}, 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}, 185 }, 186 }) 187 } 188 189 func (s *firewallerSuite) TestWatchEnvironMachines(c *gc.C) { 190 c.Assert(s.resources.Count(), gc.Equals, 0) 191 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"}, 197 }) 198 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) 203 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)) 207 wc.AssertNoChange() 208 } 209 210 func (s *firewallerSuite) TestWatch(c *gc.C) { 211 c.Assert(s.resources.Count(), gc.Equals, 0) 212 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()}, 217 }}) 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}, 231 }, 232 }) 233 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) 242 243 // Check that the Watch has consumed the initial event ("returned" in 244 // the Watch call) 245 wc1 := statetesting.NewNotifyWatcherC(c, s.State, watcher1.(state.NotifyWatcher)) 246 wc1.AssertNoChange() 247 wc2 := statetesting.NewNotifyWatcherC(c, s.State, watcher2.(state.NotifyWatcher)) 248 wc2.AssertNoChange() 249 } 250 251 func (s *firewallerSuite) TestWatchUnits(c *gc.C) { 252 c.Assert(s.resources.Count(), gc.Equals, 0) 253 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()}, 258 }}) 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}, 272 }, 273 }) 274 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) 280 281 // Check that the Watch has consumed the initial event ("returned" in 282 // the Watch call) 283 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 284 wc.AssertNoChange() 285 } 286 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) 291 292 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 293 {Tag: s.service.Tag()}, 294 }}) 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{ 299 {Result: true}, 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}, 306 }, 307 }) 308 309 // Now reset the exposed flag for the service and check again. 310 err = s.service.ClearExposed() 311 c.Assert(err, gc.IsNil) 312 313 args = params.Entities{Entities: []params.Entity{ 314 {Tag: s.service.Tag()}, 315 }} 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{ 320 {Result: false}, 321 }, 322 }) 323 } 324 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) 333 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()}, 338 }}) 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}, 352 }, 353 }) 354 355 // Now close unit 2's port and check again. 356 err = s.units[2].ClosePort("baz", 1111) 357 c.Assert(err, gc.IsNil) 358 359 args = params.Entities{Entities: []params.Entity{ 360 {Tag: s.units[2].Tag()}, 361 }} 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{}}, 367 }, 368 }) 369 } 370 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) 375 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()}, 380 }}) 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}, 394 }, 395 }) 396 397 // Now reset assign unit 2 again and check. 398 err = s.units[2].AssignToMachine(s.machines[0]) 399 c.Assert(err, gc.IsNil) 400 401 args = params.Entities{Entities: []params.Entity{ 402 {Tag: s.units[2].Tag()}, 403 }} 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()}, 409 }, 410 }) 411 } 412 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) 417 } 418 419 var commonFakeEntities = []params.Entity{ 420 {Tag: "machine-42"}, 421 {Tag: "unit-foo-0"}, 422 {Tag: "service-bar"}, 423 {Tag: "user-foo"}, 424 {Tag: "foo-bar"}, 425 {Tag: ""}, 426 } 427 428 func addFakeEntities(actual params.Entities) params.Entities { 429 for _, entity := range commonFakeEntities { 430 actual.Entities = append(actual.Entities, entity) 431 } 432 return actual 433 }