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