launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/deployer/deployer_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package deployer_test 5 6 import ( 7 gc "launchpad.net/gocheck" 8 "sort" 9 stdtesting "testing" 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/names" 15 "launchpad.net/juju-core/state" 16 "launchpad.net/juju-core/state/api/params" 17 "launchpad.net/juju-core/state/apiserver/common" 18 "launchpad.net/juju-core/state/apiserver/deployer" 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 ) 23 24 func Test(t *stdtesting.T) { 25 coretesting.MgoTestPackage(t) 26 } 27 28 type deployerSuite struct { 29 testing.JujuConnSuite 30 31 authorizer apiservertesting.FakeAuthorizer 32 33 service0 *state.Service 34 service1 *state.Service 35 machine0 *state.Machine 36 machine1 *state.Machine 37 principal0 *state.Unit 38 principal1 *state.Unit 39 subordinate0 *state.Unit 40 41 resources *common.Resources 42 deployer *deployer.DeployerAPI 43 } 44 45 var _ = gc.Suite(&deployerSuite{}) 46 47 func (s *deployerSuite) SetUpTest(c *gc.C) { 48 s.JujuConnSuite.SetUpTest(c) 49 50 // The two known machines now contain the following units: 51 // machine 0 (not authorized): mysql/1 (principal1) 52 // machine 1 (authorized): mysql/0 (principal0), logging/0 (subordinate0) 53 54 var err error 55 s.machine0, err = s.State.AddMachine("quantal", state.JobManageEnviron, state.JobHostUnits) 56 c.Assert(err, gc.IsNil) 57 58 s.machine1, err = s.State.AddMachine("quantal", state.JobHostUnits) 59 c.Assert(err, gc.IsNil) 60 61 s.service0 = s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 62 63 s.service1 = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 64 eps, err := s.State.InferEndpoints([]string{"mysql", "logging"}) 65 c.Assert(err, gc.IsNil) 66 rel, err := s.State.AddRelation(eps...) 67 c.Assert(err, gc.IsNil) 68 69 s.principal0, err = s.service0.AddUnit() 70 c.Assert(err, gc.IsNil) 71 err = s.principal0.AssignToMachine(s.machine1) 72 c.Assert(err, gc.IsNil) 73 74 s.principal1, err = s.service0.AddUnit() 75 c.Assert(err, gc.IsNil) 76 err = s.principal1.AssignToMachine(s.machine0) 77 c.Assert(err, gc.IsNil) 78 79 relUnit0, err := rel.Unit(s.principal0) 80 c.Assert(err, gc.IsNil) 81 err = relUnit0.EnterScope(nil) 82 c.Assert(err, gc.IsNil) 83 s.subordinate0, err = s.service1.Unit("logging/0") 84 c.Assert(err, gc.IsNil) 85 86 // Create a FakeAuthorizer so we can check permissions, 87 // set up assuming machine 1 has logged in. 88 s.authorizer = apiservertesting.FakeAuthorizer{ 89 Tag: names.MachineTag(s.machine1.Id()), 90 LoggedIn: true, 91 MachineAgent: true, 92 } 93 94 // Create the resource registry separately to track invocations to 95 // Register. 96 s.resources = common.NewResources() 97 98 // Create a deployer API for machine 1. 99 deployer, err := deployer.NewDeployerAPI( 100 s.State, 101 s.resources, 102 s.authorizer, 103 ) 104 c.Assert(err, gc.IsNil) 105 s.deployer = deployer 106 } 107 108 func (s *deployerSuite) TestDeployerFailsWithNonMachineAgentUser(c *gc.C) { 109 anAuthorizer := s.authorizer 110 anAuthorizer.MachineAgent = false 111 aDeployer, err := deployer.NewDeployerAPI(s.State, s.resources, anAuthorizer) 112 c.Assert(err, gc.NotNil) 113 c.Assert(aDeployer, gc.IsNil) 114 c.Assert(err, gc.ErrorMatches, "permission denied") 115 } 116 117 func (s *deployerSuite) TestWatchUnits(c *gc.C) { 118 c.Assert(s.resources.Count(), gc.Equals, 0) 119 120 args := params.Entities{Entities: []params.Entity{ 121 {Tag: "machine-1"}, 122 {Tag: "machine-0"}, 123 {Tag: "machine-42"}, 124 }} 125 result, err := s.deployer.WatchUnits(args) 126 c.Assert(err, gc.IsNil) 127 sort.Strings(result.Results[0].Changes) 128 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 129 Results: []params.StringsWatchResult{ 130 {Changes: []string{"logging/0", "mysql/0"}, StringsWatcherId: "1"}, 131 {Error: apiservertesting.ErrUnauthorized}, 132 {Error: apiservertesting.ErrUnauthorized}, 133 }, 134 }) 135 136 // Verify the resource was registered and stop when done 137 c.Assert(s.resources.Count(), gc.Equals, 1) 138 c.Assert(result.Results[0].StringsWatcherId, gc.Equals, "1") 139 resource := s.resources.Get("1") 140 defer statetesting.AssertStop(c, resource) 141 142 // Check that the Watch has consumed the initial event ("returned" in 143 // the Watch call) 144 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 145 wc.AssertNoChange() 146 } 147 148 func (s *deployerSuite) TestSetPasswords(c *gc.C) { 149 args := params.PasswordChanges{ 150 Changes: []params.PasswordChange{ 151 {Tag: "unit-mysql-0", Password: "xxx-12345678901234567890"}, 152 {Tag: "unit-mysql-1", Password: "yyy-12345678901234567890"}, 153 {Tag: "unit-logging-0", Password: "zzz-12345678901234567890"}, 154 {Tag: "unit-fake-42", Password: "abc-12345678901234567890"}, 155 }, 156 } 157 results, err := s.deployer.SetPasswords(args) 158 c.Assert(err, gc.IsNil) 159 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 160 Results: []params.ErrorResult{ 161 {nil}, 162 {apiservertesting.ErrUnauthorized}, 163 {nil}, 164 {apiservertesting.ErrUnauthorized}, 165 }, 166 }) 167 err = s.principal0.Refresh() 168 c.Assert(err, gc.IsNil) 169 changed := s.principal0.PasswordValid("xxx-12345678901234567890") 170 c.Assert(changed, gc.Equals, true) 171 err = s.subordinate0.Refresh() 172 c.Assert(err, gc.IsNil) 173 changed = s.subordinate0.PasswordValid("zzz-12345678901234567890") 174 c.Assert(changed, gc.Equals, true) 175 176 // Remove the subordinate and make sure it's detected. 177 err = s.subordinate0.EnsureDead() 178 c.Assert(err, gc.IsNil) 179 err = s.subordinate0.Remove() 180 c.Assert(err, gc.IsNil) 181 err = s.subordinate0.Refresh() 182 c.Assert(errors.IsNotFoundError(err), gc.Equals, true) 183 184 results, err = s.deployer.SetPasswords(params.PasswordChanges{ 185 Changes: []params.PasswordChange{ 186 {Tag: "unit-logging-0", Password: "blah-12345678901234567890"}, 187 }, 188 }) 189 c.Assert(err, gc.IsNil) 190 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 191 Results: []params.ErrorResult{ 192 {apiservertesting.ErrUnauthorized}, 193 }, 194 }) 195 } 196 197 func (s *deployerSuite) TestLife(c *gc.C) { 198 err := s.subordinate0.EnsureDead() 199 c.Assert(err, gc.IsNil) 200 err = s.subordinate0.Refresh() 201 c.Assert(err, gc.IsNil) 202 c.Assert(s.subordinate0.Life(), gc.Equals, state.Dead) 203 err = s.principal0.Refresh() 204 c.Assert(err, gc.IsNil) 205 c.Assert(s.principal0.Life(), gc.Equals, state.Alive) 206 207 args := params.Entities{Entities: []params.Entity{ 208 {Tag: "unit-mysql-0"}, 209 {Tag: "unit-mysql-1"}, 210 {Tag: "unit-logging-0"}, 211 {Tag: "unit-fake-42"}, 212 }} 213 result, err := s.deployer.Life(args) 214 c.Assert(err, gc.IsNil) 215 c.Assert(result, gc.DeepEquals, params.LifeResults{ 216 Results: []params.LifeResult{ 217 {Life: "alive"}, 218 {Error: apiservertesting.ErrUnauthorized}, 219 {Life: "dead"}, 220 {Error: apiservertesting.ErrUnauthorized}, 221 }, 222 }) 223 224 // Remove the subordinate and make sure it's detected. 225 err = s.subordinate0.EnsureDead() 226 c.Assert(err, gc.IsNil) 227 err = s.subordinate0.Remove() 228 c.Assert(err, gc.IsNil) 229 err = s.subordinate0.Refresh() 230 c.Assert(errors.IsNotFoundError(err), gc.Equals, true) 231 232 result, err = s.deployer.Life(params.Entities{ 233 Entities: []params.Entity{ 234 {Tag: "unit-logging-0"}, 235 }, 236 }) 237 c.Assert(err, gc.IsNil) 238 c.Assert(result, gc.DeepEquals, params.LifeResults{ 239 Results: []params.LifeResult{ 240 {Error: apiservertesting.ErrUnauthorized}, 241 }, 242 }) 243 } 244 245 func (s *deployerSuite) TestRemove(c *gc.C) { 246 c.Assert(s.principal0.Life(), gc.Equals, state.Alive) 247 c.Assert(s.subordinate0.Life(), gc.Equals, state.Alive) 248 249 // Try removing alive units - should fail. 250 args := params.Entities{Entities: []params.Entity{ 251 {Tag: "unit-mysql-0"}, 252 {Tag: "unit-mysql-1"}, 253 {Tag: "unit-logging-0"}, 254 {Tag: "unit-fake-42"}, 255 }} 256 result, err := s.deployer.Remove(args) 257 c.Assert(err, gc.IsNil) 258 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 259 Results: []params.ErrorResult{ 260 {¶ms.Error{Message: `cannot remove entity "unit-mysql-0": still alive`}}, 261 {apiservertesting.ErrUnauthorized}, 262 {¶ms.Error{Message: `cannot remove entity "unit-logging-0": still alive`}}, 263 {apiservertesting.ErrUnauthorized}, 264 }, 265 }) 266 267 err = s.principal0.Refresh() 268 c.Assert(err, gc.IsNil) 269 c.Assert(s.principal0.Life(), gc.Equals, state.Alive) 270 err = s.subordinate0.Refresh() 271 c.Assert(err, gc.IsNil) 272 c.Assert(s.subordinate0.Life(), gc.Equals, state.Alive) 273 274 // Now make the subordinate dead and try again. 275 err = s.subordinate0.EnsureDead() 276 c.Assert(err, gc.IsNil) 277 err = s.subordinate0.Refresh() 278 c.Assert(err, gc.IsNil) 279 c.Assert(s.subordinate0.Life(), gc.Equals, state.Dead) 280 281 args = params.Entities{ 282 Entities: []params.Entity{{Tag: "unit-logging-0"}}, 283 } 284 result, err = s.deployer.Remove(args) 285 c.Assert(err, gc.IsNil) 286 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 287 Results: []params.ErrorResult{{nil}}, 288 }) 289 290 err = s.subordinate0.Refresh() 291 c.Assert(errors.IsNotFoundError(err), gc.Equals, true) 292 293 // Make sure the subordinate is detected as removed. 294 result, err = s.deployer.Remove(args) 295 c.Assert(err, gc.IsNil) 296 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 297 Results: []params.ErrorResult{{apiservertesting.ErrUnauthorized}}, 298 }) 299 } 300 301 func (s *deployerSuite) TestStateAddresses(c *gc.C) { 302 err := s.machine0.SetAddresses([]instance.Address{ 303 instance.NewAddress("0.1.2.3"), 304 }) 305 c.Assert(err, gc.IsNil) 306 307 addresses, err := s.State.Addresses() 308 c.Assert(err, gc.IsNil) 309 310 result, err := s.deployer.StateAddresses() 311 c.Assert(err, gc.IsNil) 312 c.Assert(result, gc.DeepEquals, params.StringsResult{ 313 Result: addresses, 314 }) 315 } 316 317 func (s *deployerSuite) TestAPIAddresses(c *gc.C) { 318 err := s.machine0.SetAddresses([]instance.Address{ 319 instance.NewAddress("0.1.2.3"), 320 }) 321 c.Assert(err, gc.IsNil) 322 323 apiAddresses, err := s.State.APIAddresses() 324 c.Assert(err, gc.IsNil) 325 326 result, err := s.deployer.APIAddresses() 327 c.Assert(err, gc.IsNil) 328 c.Assert(result, gc.DeepEquals, params.StringsResult{ 329 Result: apiAddresses, 330 }) 331 } 332 333 func (s *deployerSuite) TestCACert(c *gc.C) { 334 result := s.deployer.CACert() 335 c.Assert(result, gc.DeepEquals, params.BytesResult{ 336 Result: s.State.CACert(), 337 }) 338 }