github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/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/state" 16 "github.com/juju/juju/state/api/params" 17 "github.com/juju/juju/state/apiserver/common" 18 commontesting "github.com/juju/juju/state/apiserver/common/testing" 19 "github.com/juju/juju/state/apiserver/firewaller" 20 apiservertesting "github.com/juju/juju/state/apiserver/testing" 21 statetesting "github.com/juju/juju/state/testing" 22 coretesting "github.com/juju/juju/testing" 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.IsNotFound) 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 got, err := s.firewaller.WatchEnvironMachines() 193 c.Assert(err, gc.IsNil) 194 want := params.StringsWatchResult{ 195 StringsWatcherId: "1", 196 Changes: []string{"0", "1", "2"}, 197 } 198 c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) 199 c.Assert(got.Changes, jc.SameContents, want.Changes) 200 201 // Verify the resources were registered and stop them when done. 202 c.Assert(s.resources.Count(), gc.Equals, 1) 203 resource := s.resources.Get("1") 204 defer statetesting.AssertStop(c, resource) 205 206 // Check that the Watch has consumed the initial event ("returned" 207 // in the Watch call) 208 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 209 wc.AssertNoChange() 210 } 211 212 func (s *firewallerSuite) TestWatch(c *gc.C) { 213 c.Assert(s.resources.Count(), gc.Equals, 0) 214 215 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 216 {Tag: s.machines[0].Tag()}, 217 {Tag: s.service.Tag()}, 218 {Tag: s.units[0].Tag()}, 219 }}) 220 result, err := s.firewaller.Watch(args) 221 c.Assert(err, gc.IsNil) 222 c.Assert(result, jc.DeepEquals, params.NotifyWatchResults{ 223 Results: []params.NotifyWatchResult{ 224 {Error: apiservertesting.ErrUnauthorized}, 225 {NotifyWatcherId: "1"}, 226 {NotifyWatcherId: "2"}, 227 {Error: apiservertesting.ErrUnauthorized}, 228 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 229 {Error: apiservertesting.NotFoundError(`service "bar"`)}, 230 {Error: apiservertesting.ErrUnauthorized}, 231 {Error: apiservertesting.ErrUnauthorized}, 232 {Error: apiservertesting.ErrUnauthorized}, 233 }, 234 }) 235 236 // Verify the resources were registered and stop when done. 237 c.Assert(s.resources.Count(), gc.Equals, 2) 238 c.Assert(result.Results[1].NotifyWatcherId, gc.Equals, "1") 239 watcher1 := s.resources.Get("1") 240 defer statetesting.AssertStop(c, watcher1) 241 c.Assert(result.Results[2].NotifyWatcherId, gc.Equals, "2") 242 watcher2 := s.resources.Get("2") 243 defer statetesting.AssertStop(c, watcher2) 244 245 // Check that the Watch has consumed the initial event ("returned" in 246 // the Watch call) 247 wc1 := statetesting.NewNotifyWatcherC(c, s.State, watcher1.(state.NotifyWatcher)) 248 wc1.AssertNoChange() 249 wc2 := statetesting.NewNotifyWatcherC(c, s.State, watcher2.(state.NotifyWatcher)) 250 wc2.AssertNoChange() 251 } 252 253 func (s *firewallerSuite) TestWatchUnits(c *gc.C) { 254 c.Assert(s.resources.Count(), gc.Equals, 0) 255 256 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 257 {Tag: s.machines[0].Tag()}, 258 {Tag: s.service.Tag()}, 259 {Tag: s.units[0].Tag()}, 260 }}) 261 result, err := s.firewaller.WatchUnits(args) 262 c.Assert(err, gc.IsNil) 263 c.Assert(result, jc.DeepEquals, params.StringsWatchResults{ 264 Results: []params.StringsWatchResult{ 265 {Changes: []string{"wordpress/0"}, StringsWatcherId: "1"}, 266 {Error: apiservertesting.ErrUnauthorized}, 267 {Error: apiservertesting.ErrUnauthorized}, 268 {Error: apiservertesting.NotFoundError("machine 42")}, 269 {Error: apiservertesting.ErrUnauthorized}, 270 {Error: apiservertesting.ErrUnauthorized}, 271 {Error: apiservertesting.ErrUnauthorized}, 272 {Error: apiservertesting.ErrUnauthorized}, 273 {Error: apiservertesting.ErrUnauthorized}, 274 }, 275 }) 276 277 // Verify the resource was registered and stop when done 278 c.Assert(s.resources.Count(), gc.Equals, 1) 279 c.Assert(result.Results[0].StringsWatcherId, gc.Equals, "1") 280 resource := s.resources.Get("1") 281 defer statetesting.AssertStop(c, resource) 282 283 // Check that the Watch has consumed the initial event ("returned" in 284 // the Watch call) 285 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 286 wc.AssertNoChange() 287 } 288 289 func (s *firewallerSuite) TestGetExposed(c *gc.C) { 290 // Set the service to exposed first. 291 err := s.service.SetExposed() 292 c.Assert(err, gc.IsNil) 293 294 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 295 {Tag: s.service.Tag()}, 296 }}) 297 result, err := s.firewaller.GetExposed(args) 298 c.Assert(err, gc.IsNil) 299 c.Assert(result, jc.DeepEquals, params.BoolResults{ 300 Results: []params.BoolResult{ 301 {Result: true}, 302 {Error: apiservertesting.ErrUnauthorized}, 303 {Error: apiservertesting.ErrUnauthorized}, 304 {Error: apiservertesting.NotFoundError(`service "bar"`)}, 305 {Error: apiservertesting.ErrUnauthorized}, 306 {Error: apiservertesting.ErrUnauthorized}, 307 {Error: apiservertesting.ErrUnauthorized}, 308 }, 309 }) 310 311 // Now reset the exposed flag for the service and check again. 312 err = s.service.ClearExposed() 313 c.Assert(err, gc.IsNil) 314 315 args = params.Entities{Entities: []params.Entity{ 316 {Tag: s.service.Tag()}, 317 }} 318 result, err = s.firewaller.GetExposed(args) 319 c.Assert(err, gc.IsNil) 320 c.Assert(result, jc.DeepEquals, params.BoolResults{ 321 Results: []params.BoolResult{ 322 {Result: false}, 323 }, 324 }) 325 } 326 327 func (s *firewallerSuite) TestOpenedPorts(c *gc.C) { 328 // Open some ports on two of the units. 329 err := s.units[0].OpenPort("foo", 1234) 330 c.Assert(err, gc.IsNil) 331 err = s.units[0].OpenPort("bar", 4321) 332 c.Assert(err, gc.IsNil) 333 err = s.units[2].OpenPort("baz", 1111) 334 c.Assert(err, gc.IsNil) 335 336 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 337 {Tag: s.units[0].Tag()}, 338 {Tag: s.units[1].Tag()}, 339 {Tag: s.units[2].Tag()}, 340 }}) 341 result, err := s.firewaller.OpenedPorts(args) 342 c.Assert(err, gc.IsNil) 343 c.Assert(result, jc.DeepEquals, params.PortsResults{ 344 Results: []params.PortsResult{ 345 {Ports: []instance.Port{{"bar", 4321}, {"foo", 1234}}}, 346 {Ports: []instance.Port{}}, 347 {Ports: []instance.Port{{"baz", 1111}}}, 348 {Error: apiservertesting.ErrUnauthorized}, 349 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 350 {Error: apiservertesting.ErrUnauthorized}, 351 {Error: apiservertesting.ErrUnauthorized}, 352 {Error: apiservertesting.ErrUnauthorized}, 353 {Error: apiservertesting.ErrUnauthorized}, 354 }, 355 }) 356 357 // Now close unit 2's port and check again. 358 err = s.units[2].ClosePort("baz", 1111) 359 c.Assert(err, gc.IsNil) 360 361 args = params.Entities{Entities: []params.Entity{ 362 {Tag: s.units[2].Tag()}, 363 }} 364 result, err = s.firewaller.OpenedPorts(args) 365 c.Assert(err, gc.IsNil) 366 c.Assert(result, jc.DeepEquals, params.PortsResults{ 367 Results: []params.PortsResult{ 368 {Ports: []instance.Port{}}, 369 }, 370 }) 371 } 372 373 func (s *firewallerSuite) TestGetAssignedMachine(c *gc.C) { 374 // Unassign a unit first. 375 err := s.units[2].UnassignFromMachine() 376 c.Assert(err, gc.IsNil) 377 378 args := addFakeEntities(params.Entities{Entities: []params.Entity{ 379 {Tag: s.units[0].Tag()}, 380 {Tag: s.units[1].Tag()}, 381 {Tag: s.units[2].Tag()}, 382 }}) 383 result, err := s.firewaller.GetAssignedMachine(args) 384 c.Assert(err, gc.IsNil) 385 c.Assert(result, jc.DeepEquals, params.StringResults{ 386 Results: []params.StringResult{ 387 {Result: s.machines[0].Tag()}, 388 {Result: s.machines[1].Tag()}, 389 {Error: apiservertesting.NotAssignedError("wordpress/2")}, 390 {Error: apiservertesting.ErrUnauthorized}, 391 {Error: apiservertesting.NotFoundError(`unit "foo/0"`)}, 392 {Error: apiservertesting.ErrUnauthorized}, 393 {Error: apiservertesting.ErrUnauthorized}, 394 {Error: apiservertesting.ErrUnauthorized}, 395 {Error: apiservertesting.ErrUnauthorized}, 396 }, 397 }) 398 399 // Now reset assign unit 2 again and check. 400 err = s.units[2].AssignToMachine(s.machines[0]) 401 c.Assert(err, gc.IsNil) 402 403 args = params.Entities{Entities: []params.Entity{ 404 {Tag: s.units[2].Tag()}, 405 }} 406 result, err = s.firewaller.GetAssignedMachine(args) 407 c.Assert(err, gc.IsNil) 408 c.Assert(result, jc.DeepEquals, params.StringResults{ 409 Results: []params.StringResult{ 410 {Result: s.machines[0].Tag()}, 411 }, 412 }) 413 } 414 415 func (s *firewallerSuite) assertLife(c *gc.C, index int, expectLife state.Life) { 416 err := s.machines[index].Refresh() 417 c.Assert(err, gc.IsNil) 418 c.Assert(s.machines[index].Life(), gc.Equals, expectLife) 419 } 420 421 var commonFakeEntities = []params.Entity{ 422 {Tag: "machine-42"}, 423 {Tag: "unit-foo-0"}, 424 {Tag: "service-bar"}, 425 {Tag: "user-foo"}, 426 {Tag: "foo-bar"}, 427 {Tag: ""}, 428 } 429 430 func addFakeEntities(actual params.Entities) params.Entities { 431 for _, entity := range commonFakeEntities { 432 actual.Entities = append(actual.Entities, entity) 433 } 434 return actual 435 }