github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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 "sort" 8 stdtesting "testing" 9 10 "github.com/juju/errors" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/apiserver/deployer" 16 "github.com/juju/juju/apiserver/params" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/juju/testing" 19 "github.com/juju/juju/network" 20 "github.com/juju/juju/state" 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 deployerSuite struct { 30 testing.JujuConnSuite 31 32 authorizer apiservertesting.FakeAuthorizer 33 34 service0 *state.Service 35 service1 *state.Service 36 machine0 *state.Machine 37 machine1 *state.Machine 38 principal0 *state.Unit 39 principal1 *state.Unit 40 subordinate0 *state.Unit 41 42 resources *common.Resources 43 deployer *deployer.DeployerAPI 44 } 45 46 var _ = gc.Suite(&deployerSuite{}) 47 48 func (s *deployerSuite) SetUpTest(c *gc.C) { 49 s.JujuConnSuite.SetUpTest(c) 50 51 // The two known machines now contain the following units: 52 // machine 0 (not authorized): mysql/1 (principal1) 53 // machine 1 (authorized): mysql/0 (principal0), logging/0 (subordinate0) 54 55 var err error 56 s.machine0, err = s.State.AddMachine("quantal", state.JobManageModel, state.JobHostUnits) 57 c.Assert(err, jc.ErrorIsNil) 58 59 s.machine1, err = s.State.AddMachine("quantal", state.JobHostUnits) 60 c.Assert(err, jc.ErrorIsNil) 61 62 s.service0 = s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 63 64 s.service1 = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 65 eps, err := s.State.InferEndpoints("mysql", "logging") 66 c.Assert(err, jc.ErrorIsNil) 67 rel, err := s.State.AddRelation(eps...) 68 c.Assert(err, jc.ErrorIsNil) 69 70 s.principal0, err = s.service0.AddUnit() 71 c.Assert(err, jc.ErrorIsNil) 72 err = s.principal0.AssignToMachine(s.machine1) 73 c.Assert(err, jc.ErrorIsNil) 74 75 s.principal1, err = s.service0.AddUnit() 76 c.Assert(err, jc.ErrorIsNil) 77 err = s.principal1.AssignToMachine(s.machine0) 78 c.Assert(err, jc.ErrorIsNil) 79 80 relUnit0, err := rel.Unit(s.principal0) 81 c.Assert(err, jc.ErrorIsNil) 82 err = relUnit0.EnterScope(nil) 83 c.Assert(err, jc.ErrorIsNil) 84 s.subordinate0, err = s.State.Unit("logging/0") 85 c.Assert(err, jc.ErrorIsNil) 86 87 // Create a FakeAuthorizer so we can check permissions, 88 // set up assuming machine 1 has logged in. 89 s.authorizer = apiservertesting.FakeAuthorizer{ 90 Tag: s.machine1.Tag(), 91 } 92 93 // Create the resource registry separately to track invocations to 94 // Register. 95 s.resources = common.NewResources() 96 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 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, jc.ErrorIsNil) 105 s.deployer = deployer 106 } 107 108 func (s *deployerSuite) TestDeployerFailsWithNonMachineAgentUser(c *gc.C) { 109 anAuthorizer := s.authorizer 110 anAuthorizer.Tag = s.AdminUserTag(c) 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, jc.ErrorIsNil) 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.EntityPasswords{ 150 Changes: []params.EntityPassword{ 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, jc.ErrorIsNil) 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, jc.ErrorIsNil) 169 changed := s.principal0.PasswordValid("xxx-12345678901234567890") 170 c.Assert(changed, jc.IsTrue) 171 err = s.subordinate0.Refresh() 172 c.Assert(err, jc.ErrorIsNil) 173 changed = s.subordinate0.PasswordValid("zzz-12345678901234567890") 174 c.Assert(changed, jc.IsTrue) 175 176 // Remove the subordinate and make sure it's detected. 177 err = s.subordinate0.EnsureDead() 178 c.Assert(err, jc.ErrorIsNil) 179 err = s.subordinate0.Remove() 180 c.Assert(err, jc.ErrorIsNil) 181 err = s.subordinate0.Refresh() 182 c.Assert(err, jc.Satisfies, errors.IsNotFound) 183 184 results, err = s.deployer.SetPasswords(params.EntityPasswords{ 185 Changes: []params.EntityPassword{ 186 {Tag: "unit-logging-0", Password: "blah-12345678901234567890"}, 187 }, 188 }) 189 c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) 200 err = s.subordinate0.Refresh() 201 c.Assert(err, jc.ErrorIsNil) 202 c.Assert(s.subordinate0.Life(), gc.Equals, state.Dead) 203 err = s.principal0.Refresh() 204 c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) 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, jc.ErrorIsNil) 227 err = s.subordinate0.Remove() 228 c.Assert(err, jc.ErrorIsNil) 229 err = s.subordinate0.Refresh() 230 c.Assert(err, jc.Satisfies, errors.IsNotFound) 231 232 result, err = s.deployer.Life(params.Entities{ 233 Entities: []params.Entity{ 234 {Tag: "unit-logging-0"}, 235 }, 236 }) 237 c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) 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, jc.ErrorIsNil) 269 c.Assert(s.principal0.Life(), gc.Equals, state.Alive) 270 err = s.subordinate0.Refresh() 271 c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) 277 err = s.subordinate0.Refresh() 278 c.Assert(err, jc.ErrorIsNil) 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, jc.ErrorIsNil) 286 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 287 Results: []params.ErrorResult{{nil}}, 288 }) 289 290 err = s.subordinate0.Refresh() 291 c.Assert(err, jc.Satisfies, errors.IsNotFound) 292 293 // Make sure the subordinate is detected as removed. 294 result, err = s.deployer.Remove(args) 295 c.Assert(err, jc.ErrorIsNil) 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.SetProviderAddresses(network.NewAddress("0.1.2.3")) 303 c.Assert(err, jc.ErrorIsNil) 304 305 addresses, err := s.State.Addresses() 306 c.Assert(err, jc.ErrorIsNil) 307 308 result, err := s.deployer.StateAddresses() 309 c.Assert(err, jc.ErrorIsNil) 310 c.Assert(result, gc.DeepEquals, params.StringsResult{ 311 Result: addresses, 312 }) 313 } 314 315 func (s *deployerSuite) TestAPIAddresses(c *gc.C) { 316 hostPorts := [][]network.HostPort{ 317 network.NewHostPorts(1234, "0.1.2.3"), 318 } 319 err := s.State.SetAPIHostPorts(hostPorts) 320 c.Assert(err, jc.ErrorIsNil) 321 322 result, err := s.deployer.APIAddresses() 323 c.Assert(err, jc.ErrorIsNil) 324 c.Assert(result, gc.DeepEquals, params.StringsResult{ 325 Result: []string{"0.1.2.3:1234"}, 326 }) 327 } 328 329 func (s *deployerSuite) TestCACert(c *gc.C) { 330 result := s.deployer.CACert() 331 c.Assert(result, gc.DeepEquals, params.BytesResult{ 332 Result: []byte(s.State.CACert()), 333 }) 334 }