launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/provisioner/provisioner_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner_test 5 6 import ( 7 "fmt" 8 gc "launchpad.net/gocheck" 9 stdtesting "testing" 10 11 "launchpad.net/juju-core/constraints" 12 "launchpad.net/juju-core/errors" 13 "launchpad.net/juju-core/instance" 14 "launchpad.net/juju-core/juju/osenv" 15 "launchpad.net/juju-core/juju/testing" 16 "launchpad.net/juju-core/state" 17 "launchpad.net/juju-core/state/api/params" 18 "launchpad.net/juju-core/state/apiserver/common" 19 commontesting "launchpad.net/juju-core/state/apiserver/common/testing" 20 "launchpad.net/juju-core/state/apiserver/provisioner" 21 apiservertesting "launchpad.net/juju-core/state/apiserver/testing" 22 statetesting "launchpad.net/juju-core/state/testing" 23 coretesting "launchpad.net/juju-core/testing" 24 jc "launchpad.net/juju-core/testing/checkers" 25 "launchpad.net/juju-core/version" 26 ) 27 28 func Test(t *stdtesting.T) { 29 coretesting.MgoTestPackage(t) 30 } 31 32 type provisionerSuite struct { 33 testing.JujuConnSuite 34 35 machines []*state.Machine 36 37 authorizer apiservertesting.FakeAuthorizer 38 resources *common.Resources 39 provisioner *provisioner.ProvisionerAPI 40 } 41 42 var _ = gc.Suite(&provisionerSuite{}) 43 44 func (s *provisionerSuite) SetUpTest(c *gc.C) { 45 s.setUpTest(c, false) 46 } 47 48 func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) { 49 s.JujuConnSuite.SetUpTest(c) 50 51 // Reset previous machines (if any) and create 3 machines 52 // for the tests, plus an optional state server machine. 53 s.machines = nil 54 // Note that the specific machine ids allocated are assumed 55 // to be numerically consecutive from zero. 56 if withStateServer { 57 s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State)) 58 } 59 for i := 0; i < 3; i++ { 60 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 61 c.Check(err, gc.IsNil) 62 s.machines = append(s.machines, machine) 63 } 64 65 // Create a FakeAuthorizer so we can check permissions, 66 // set up assuming we logged in as the environment manager. 67 s.authorizer = apiservertesting.FakeAuthorizer{ 68 LoggedIn: true, 69 EnvironManager: true, 70 } 71 72 // Create the resource registry separately to track invocations to 73 // Register. 74 s.resources = common.NewResources() 75 76 // Create a provisioner API for the machine. 77 provisionerAPI, err := provisioner.NewProvisionerAPI( 78 s.State, 79 s.resources, 80 s.authorizer, 81 ) 82 c.Assert(err, gc.IsNil) 83 s.provisioner = provisionerAPI 84 } 85 86 type withoutStateServerSuite struct { 87 provisionerSuite 88 *commontesting.EnvironWatcherTest 89 } 90 91 var _ = gc.Suite(&withoutStateServerSuite{}) 92 93 func (s *withoutStateServerSuite) SetUpTest(c *gc.C) { 94 s.setUpTest(c, false) 95 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets) 96 } 97 98 func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) { 99 anAuthorizer := s.authorizer 100 anAuthorizer.MachineAgent = false 101 anAuthorizer.EnvironManager = true 102 // Works with an environment manager, which is not a machine agent. 103 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 104 c.Assert(err, gc.IsNil) 105 c.Assert(aProvisioner, gc.NotNil) 106 107 // But fails with neither a machine agent or an environment manager. 108 anAuthorizer.EnvironManager = false 109 aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 110 c.Assert(err, gc.NotNil) 111 c.Assert(aProvisioner, gc.IsNil) 112 c.Assert(err, gc.ErrorMatches, "permission denied") 113 } 114 115 func (s *withoutStateServerSuite) TestSetPasswords(c *gc.C) { 116 args := params.PasswordChanges{ 117 Changes: []params.PasswordChange{ 118 {Tag: s.machines[0].Tag(), Password: "xxx0-1234567890123457890"}, 119 {Tag: s.machines[1].Tag(), Password: "xxx1-1234567890123457890"}, 120 {Tag: s.machines[2].Tag(), Password: "xxx2-1234567890123457890"}, 121 {Tag: "machine-42", Password: "foo"}, 122 {Tag: "unit-foo-0", Password: "zzz"}, 123 {Tag: "service-bar", Password: "abc"}, 124 }, 125 } 126 results, err := s.provisioner.SetPasswords(args) 127 c.Assert(err, gc.IsNil) 128 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 129 Results: []params.ErrorResult{ 130 {nil}, 131 {nil}, 132 {nil}, 133 {apiservertesting.NotFoundError("machine 42")}, 134 {apiservertesting.ErrUnauthorized}, 135 {apiservertesting.ErrUnauthorized}, 136 }, 137 }) 138 139 // Verify the changes to both machines succeeded. 140 for i, machine := range s.machines { 141 c.Logf("trying %q password", machine.Tag()) 142 err = machine.Refresh() 143 c.Assert(err, gc.IsNil) 144 changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i)) 145 c.Assert(changed, jc.IsTrue) 146 } 147 } 148 149 func (s *withoutStateServerSuite) TestShortSetPasswords(c *gc.C) { 150 args := params.PasswordChanges{ 151 Changes: []params.PasswordChange{ 152 {Tag: s.machines[1].Tag(), Password: "xxx1"}, 153 }, 154 } 155 results, err := s.provisioner.SetPasswords(args) 156 c.Assert(err, gc.IsNil) 157 c.Assert(results.Results, gc.HasLen, 1) 158 c.Assert(results.Results[0].Error, gc.ErrorMatches, 159 "password is only 4 bytes long, and is not a valid Agent password") 160 } 161 162 func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) { 163 // NOTE: This and the next call serve to test the two 164 // different authorization schemes: 165 // 1. Machine agents can access their own machine and 166 // any container that has their own machine as parent; 167 // 2. Environment managers can access any machine without 168 // a parent. 169 // There's no need to repeat this test for each method, 170 // because the authorization logic is common. 171 172 // Login as a machine agent for machine 0. 173 anAuthorizer := s.authorizer 174 anAuthorizer.MachineAgent = true 175 anAuthorizer.EnvironManager = false 176 anAuthorizer.Tag = s.machines[0].Tag() 177 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 178 c.Assert(err, gc.IsNil) 179 c.Assert(aProvisioner, gc.NotNil) 180 181 // Make the machine dead before trying to add containers. 182 err = s.machines[0].EnsureDead() 183 c.Assert(err, gc.IsNil) 184 185 // Create some containers to work on. 186 template := state.MachineTemplate{ 187 Series: "quantal", 188 Jobs: []state.MachineJob{state.JobHostUnits}, 189 } 190 var containers []*state.Machine 191 for i := 0; i < 3; i++ { 192 container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC) 193 c.Check(err, gc.IsNil) 194 containers = append(containers, container) 195 } 196 // Make one container dead. 197 err = containers[1].EnsureDead() 198 c.Assert(err, gc.IsNil) 199 200 args := params.Entities{Entities: []params.Entity{ 201 {Tag: s.machines[0].Tag()}, 202 {Tag: s.machines[1].Tag()}, 203 {Tag: containers[0].Tag()}, 204 {Tag: containers[1].Tag()}, 205 {Tag: containers[2].Tag()}, 206 {Tag: "machine-42"}, 207 {Tag: "unit-foo-0"}, 208 {Tag: "service-bar"}, 209 }} 210 result, err := aProvisioner.Life(args) 211 c.Assert(err, gc.IsNil) 212 c.Assert(result, gc.DeepEquals, params.LifeResults{ 213 Results: []params.LifeResult{ 214 {Life: "dead"}, 215 {Error: apiservertesting.ErrUnauthorized}, 216 {Life: "alive"}, 217 {Life: "dead"}, 218 {Life: "alive"}, 219 {Error: apiservertesting.ErrUnauthorized}, 220 {Error: apiservertesting.ErrUnauthorized}, 221 {Error: apiservertesting.ErrUnauthorized}, 222 }, 223 }) 224 } 225 226 func (s *withoutStateServerSuite) TestLifeAsEnvironManager(c *gc.C) { 227 err := s.machines[1].EnsureDead() 228 c.Assert(err, gc.IsNil) 229 err = s.machines[1].Refresh() 230 c.Assert(err, gc.IsNil) 231 c.Assert(s.machines[0].Life(), gc.Equals, state.Alive) 232 c.Assert(s.machines[1].Life(), gc.Equals, state.Dead) 233 c.Assert(s.machines[2].Life(), gc.Equals, state.Alive) 234 235 args := params.Entities{Entities: []params.Entity{ 236 {Tag: s.machines[0].Tag()}, 237 {Tag: s.machines[1].Tag()}, 238 {Tag: s.machines[2].Tag()}, 239 {Tag: "machine-42"}, 240 {Tag: "unit-foo-0"}, 241 {Tag: "service-bar"}, 242 }} 243 result, err := s.provisioner.Life(args) 244 c.Assert(err, gc.IsNil) 245 c.Assert(result, gc.DeepEquals, params.LifeResults{ 246 Results: []params.LifeResult{ 247 {Life: "alive"}, 248 {Life: "dead"}, 249 {Life: "alive"}, 250 {Error: apiservertesting.NotFoundError("machine 42")}, 251 {Error: apiservertesting.ErrUnauthorized}, 252 {Error: apiservertesting.ErrUnauthorized}, 253 }, 254 }) 255 256 // Remove the subordinate and make sure it's detected. 257 err = s.machines[1].Remove() 258 c.Assert(err, gc.IsNil) 259 err = s.machines[1].Refresh() 260 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 261 262 result, err = s.provisioner.Life(params.Entities{ 263 Entities: []params.Entity{ 264 {Tag: s.machines[1].Tag()}, 265 }, 266 }) 267 c.Assert(err, gc.IsNil) 268 c.Assert(result, gc.DeepEquals, params.LifeResults{ 269 Results: []params.LifeResult{ 270 {Error: apiservertesting.NotFoundError("machine 1")}, 271 }, 272 }) 273 } 274 275 func (s *withoutStateServerSuite) TestRemove(c *gc.C) { 276 err := s.machines[1].EnsureDead() 277 c.Assert(err, gc.IsNil) 278 s.assertLife(c, 0, state.Alive) 279 s.assertLife(c, 1, state.Dead) 280 s.assertLife(c, 2, state.Alive) 281 282 args := params.Entities{Entities: []params.Entity{ 283 {Tag: s.machines[0].Tag()}, 284 {Tag: s.machines[1].Tag()}, 285 {Tag: s.machines[2].Tag()}, 286 {Tag: "machine-42"}, 287 {Tag: "unit-foo-0"}, 288 {Tag: "service-bar"}, 289 }} 290 result, err := s.provisioner.Remove(args) 291 c.Assert(err, gc.IsNil) 292 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 293 Results: []params.ErrorResult{ 294 {¶ms.Error{Message: `cannot remove entity "machine-0": still alive`}}, 295 {nil}, 296 {¶ms.Error{Message: `cannot remove entity "machine-2": still alive`}}, 297 {apiservertesting.NotFoundError("machine 42")}, 298 {apiservertesting.ErrUnauthorized}, 299 {apiservertesting.ErrUnauthorized}, 300 }, 301 }) 302 303 // Verify the changes. 304 s.assertLife(c, 0, state.Alive) 305 err = s.machines[1].Refresh() 306 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 307 s.assertLife(c, 2, state.Alive) 308 } 309 310 func (s *withoutStateServerSuite) TestSetStatus(c *gc.C) { 311 err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 312 c.Assert(err, gc.IsNil) 313 err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil) 314 c.Assert(err, gc.IsNil) 315 err = s.machines[2].SetStatus(params.StatusError, "not really", nil) 316 c.Assert(err, gc.IsNil) 317 318 args := params.SetStatus{ 319 Entities: []params.SetEntityStatus{ 320 {Tag: s.machines[0].Tag(), Status: params.StatusError, Info: "not really"}, 321 {Tag: s.machines[1].Tag(), Status: params.StatusStopped, Info: "foobar"}, 322 {Tag: s.machines[2].Tag(), Status: params.StatusStarted, Info: "again"}, 323 {Tag: "machine-42", Status: params.StatusStarted, Info: "blah"}, 324 {Tag: "unit-foo-0", Status: params.StatusStopped, Info: "foobar"}, 325 {Tag: "service-bar", Status: params.StatusStopped, Info: "foobar"}, 326 }} 327 result, err := s.provisioner.SetStatus(args) 328 c.Assert(err, gc.IsNil) 329 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 330 Results: []params.ErrorResult{ 331 {nil}, 332 {nil}, 333 {nil}, 334 {apiservertesting.NotFoundError("machine 42")}, 335 {apiservertesting.ErrUnauthorized}, 336 {apiservertesting.ErrUnauthorized}, 337 }, 338 }) 339 340 // Verify the changes. 341 s.assertStatus(c, 0, params.StatusError, "not really") 342 s.assertStatus(c, 1, params.StatusStopped, "foobar") 343 s.assertStatus(c, 2, params.StatusStarted, "again") 344 } 345 346 func (s *withoutStateServerSuite) TestEnsureDead(c *gc.C) { 347 err := s.machines[1].EnsureDead() 348 c.Assert(err, gc.IsNil) 349 s.assertLife(c, 0, state.Alive) 350 s.assertLife(c, 1, state.Dead) 351 s.assertLife(c, 2, state.Alive) 352 353 args := params.Entities{Entities: []params.Entity{ 354 {Tag: s.machines[0].Tag()}, 355 {Tag: s.machines[1].Tag()}, 356 {Tag: s.machines[2].Tag()}, 357 {Tag: "machine-42"}, 358 {Tag: "unit-foo-0"}, 359 {Tag: "service-bar"}, 360 }} 361 result, err := s.provisioner.EnsureDead(args) 362 c.Assert(err, gc.IsNil) 363 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 364 Results: []params.ErrorResult{ 365 {nil}, 366 {nil}, 367 {nil}, 368 {apiservertesting.NotFoundError("machine 42")}, 369 {apiservertesting.ErrUnauthorized}, 370 {apiservertesting.ErrUnauthorized}, 371 }, 372 }) 373 374 // Verify the changes. 375 s.assertLife(c, 0, state.Dead) 376 s.assertLife(c, 1, state.Dead) 377 s.assertLife(c, 2, state.Dead) 378 } 379 380 func (s *withoutStateServerSuite) assertLife(c *gc.C, index int, expectLife state.Life) { 381 err := s.machines[index].Refresh() 382 c.Assert(err, gc.IsNil) 383 c.Assert(s.machines[index].Life(), gc.Equals, expectLife) 384 } 385 386 func (s *withoutStateServerSuite) assertStatus(c *gc.C, index int, expectStatus params.Status, expectInfo string) { 387 status, info, _, err := s.machines[index].Status() 388 c.Assert(err, gc.IsNil) 389 c.Assert(status, gc.Equals, expectStatus) 390 c.Assert(info, gc.Equals, expectInfo) 391 } 392 393 func (s *withoutStateServerSuite) TestWatchContainers(c *gc.C) { 394 c.Assert(s.resources.Count(), gc.Equals, 0) 395 396 args := params.WatchContainers{Params: []params.WatchContainer{ 397 {MachineTag: s.machines[0].Tag(), ContainerType: string(instance.LXC)}, 398 {MachineTag: s.machines[1].Tag(), ContainerType: string(instance.KVM)}, 399 {MachineTag: "machine-42", ContainerType: ""}, 400 {MachineTag: "unit-foo-0", ContainerType: ""}, 401 {MachineTag: "service-bar", ContainerType: ""}, 402 }} 403 result, err := s.provisioner.WatchContainers(args) 404 c.Assert(err, gc.IsNil) 405 c.Assert(result, jc.DeepEquals, params.StringsWatchResults{ 406 Results: []params.StringsWatchResult{ 407 {StringsWatcherId: "1", Changes: []string{}}, 408 {StringsWatcherId: "2", Changes: []string{}}, 409 {Error: apiservertesting.NotFoundError("machine 42")}, 410 {Error: apiservertesting.ErrUnauthorized}, 411 {Error: apiservertesting.ErrUnauthorized}, 412 }, 413 }) 414 415 // Verify the resources were registered and stop them when done. 416 c.Assert(s.resources.Count(), gc.Equals, 2) 417 m0Watcher := s.resources.Get("1") 418 defer statetesting.AssertStop(c, m0Watcher) 419 m1Watcher := s.resources.Get("2") 420 defer statetesting.AssertStop(c, m1Watcher) 421 422 // Check that the Watch has consumed the initial event ("returned" 423 // in the Watch call) 424 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 425 wc0.AssertNoChange() 426 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 427 wc1.AssertNoChange() 428 } 429 430 func (s *withoutStateServerSuite) TestWatchAllContainers(c *gc.C) { 431 c.Assert(s.resources.Count(), gc.Equals, 0) 432 433 args := params.WatchContainers{Params: []params.WatchContainer{ 434 {MachineTag: s.machines[0].Tag()}, 435 {MachineTag: s.machines[1].Tag()}, 436 {MachineTag: "machine-42"}, 437 {MachineTag: "unit-foo-0"}, 438 {MachineTag: "service-bar"}, 439 }} 440 result, err := s.provisioner.WatchAllContainers(args) 441 c.Assert(err, gc.IsNil) 442 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 443 Results: []params.StringsWatchResult{ 444 {StringsWatcherId: "1", Changes: []string{}}, 445 {StringsWatcherId: "2", Changes: []string{}}, 446 {Error: apiservertesting.NotFoundError("machine 42")}, 447 {Error: apiservertesting.ErrUnauthorized}, 448 {Error: apiservertesting.ErrUnauthorized}, 449 }, 450 }) 451 452 // Verify the resources were registered and stop them when done. 453 c.Assert(s.resources.Count(), gc.Equals, 2) 454 m0Watcher := s.resources.Get("1") 455 defer statetesting.AssertStop(c, m0Watcher) 456 m1Watcher := s.resources.Get("2") 457 defer statetesting.AssertStop(c, m1Watcher) 458 459 // Check that the Watch has consumed the initial event ("returned" 460 // in the Watch call) 461 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 462 wc0.AssertNoChange() 463 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 464 wc1.AssertNoChange() 465 } 466 467 func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) { 468 // Now test it with a non-environment manager and make sure 469 // the secret attributes are masked. 470 anAuthorizer := s.authorizer 471 anAuthorizer.MachineAgent = true 472 anAuthorizer.EnvironManager = false 473 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, 474 anAuthorizer) 475 c.Assert(err, gc.IsNil) 476 s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets) 477 } 478 479 func (s *withoutStateServerSuite) TestStatus(c *gc.C) { 480 err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 481 c.Assert(err, gc.IsNil) 482 err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil) 483 c.Assert(err, gc.IsNil) 484 err = s.machines[2].SetStatus(params.StatusError, "not really", nil) 485 c.Assert(err, gc.IsNil) 486 487 args := params.Entities{Entities: []params.Entity{ 488 {Tag: s.machines[0].Tag()}, 489 {Tag: s.machines[1].Tag()}, 490 {Tag: s.machines[2].Tag()}, 491 {Tag: "machine-42"}, 492 {Tag: "unit-foo-0"}, 493 {Tag: "service-bar"}, 494 }} 495 result, err := s.provisioner.Status(args) 496 c.Assert(err, gc.IsNil) 497 c.Assert(result, gc.DeepEquals, params.StatusResults{ 498 Results: []params.StatusResult{ 499 {Status: params.StatusStarted, Info: "blah"}, 500 {Status: params.StatusStopped, Info: "foo"}, 501 {Status: params.StatusError, Info: "not really"}, 502 {Error: apiservertesting.NotFoundError("machine 42")}, 503 {Error: apiservertesting.ErrUnauthorized}, 504 {Error: apiservertesting.ErrUnauthorized}, 505 }, 506 }) 507 } 508 509 func (s *withoutStateServerSuite) TestSeries(c *gc.C) { 510 // Add a machine with different series. 511 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 512 c.Assert(err, gc.IsNil) 513 514 args := params.Entities{Entities: []params.Entity{ 515 {Tag: s.machines[0].Tag()}, 516 {Tag: foobarMachine.Tag()}, 517 {Tag: s.machines[2].Tag()}, 518 {Tag: "machine-42"}, 519 {Tag: "unit-foo-0"}, 520 {Tag: "service-bar"}, 521 }} 522 result, err := s.provisioner.Series(args) 523 c.Assert(err, gc.IsNil) 524 c.Assert(result, gc.DeepEquals, params.StringResults{ 525 Results: []params.StringResult{ 526 {Result: s.machines[0].Series()}, 527 {Result: foobarMachine.Series()}, 528 {Result: s.machines[2].Series()}, 529 {Error: apiservertesting.NotFoundError("machine 42")}, 530 {Error: apiservertesting.ErrUnauthorized}, 531 {Error: apiservertesting.ErrUnauthorized}, 532 }, 533 }) 534 } 535 536 func (s *withoutStateServerSuite) TestConstraints(c *gc.C) { 537 // Add a machine with some constraints. 538 template := state.MachineTemplate{ 539 Series: "quantal", 540 Jobs: []state.MachineJob{state.JobHostUnits}, 541 Constraints: constraints.MustParse("cpu-cores=123", "mem=8G"), 542 } 543 consMachine, err := s.State.AddOneMachine(template) 544 c.Assert(err, gc.IsNil) 545 546 machine0Constraints, err := s.machines[0].Constraints() 547 c.Assert(err, gc.IsNil) 548 549 args := params.Entities{Entities: []params.Entity{ 550 {Tag: s.machines[0].Tag()}, 551 {Tag: consMachine.Tag()}, 552 {Tag: "machine-42"}, 553 {Tag: "unit-foo-0"}, 554 {Tag: "service-bar"}, 555 }} 556 result, err := s.provisioner.Constraints(args) 557 c.Assert(err, gc.IsNil) 558 c.Assert(result, gc.DeepEquals, params.ConstraintsResults{ 559 Results: []params.ConstraintsResult{ 560 {Constraints: machine0Constraints}, 561 {Constraints: template.Constraints}, 562 {Error: apiservertesting.NotFoundError("machine 42")}, 563 {Error: apiservertesting.ErrUnauthorized}, 564 {Error: apiservertesting.ErrUnauthorized}, 565 }, 566 }) 567 } 568 569 func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) { 570 // Provision machine 0 first. 571 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 572 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars) 573 c.Assert(err, gc.IsNil) 574 575 args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{ 576 {Tag: s.machines[0].Tag(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil}, 577 {Tag: s.machines[1].Tag(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars}, 578 {Tag: s.machines[2].Tag(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil}, 579 {Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil}, 580 {Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil}, 581 {Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil}, 582 }} 583 result, err := s.provisioner.SetProvisioned(args) 584 c.Assert(err, gc.IsNil) 585 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 586 Results: []params.ErrorResult{ 587 {¶ms.Error{ 588 Message: `cannot set instance data for machine "0": already set`, 589 }}, 590 {nil}, 591 {nil}, 592 {apiservertesting.NotFoundError("machine 42")}, 593 {apiservertesting.ErrUnauthorized}, 594 {apiservertesting.ErrUnauthorized}, 595 }, 596 }) 597 598 // Verify machine 1 and 2 were provisioned. 599 c.Assert(s.machines[1].Refresh(), gc.IsNil) 600 c.Assert(s.machines[2].Refresh(), gc.IsNil) 601 602 instanceId, err := s.machines[1].InstanceId() 603 c.Assert(err, gc.IsNil) 604 c.Check(instanceId, gc.Equals, instance.Id("i-will")) 605 instanceId, err = s.machines[2].InstanceId() 606 c.Assert(err, gc.IsNil) 607 c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) 608 c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) 609 c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) 610 gotHardware, err := s.machines[1].HardwareCharacteristics() 611 c.Assert(err, gc.IsNil) 612 c.Check(gotHardware, gc.DeepEquals, &hwChars) 613 } 614 615 func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) { 616 // Provision 2 machines first. 617 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) 618 c.Assert(err, gc.IsNil) 619 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 620 err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) 621 c.Assert(err, gc.IsNil) 622 623 args := params.Entities{Entities: []params.Entity{ 624 {Tag: s.machines[0].Tag()}, 625 {Tag: s.machines[1].Tag()}, 626 {Tag: s.machines[2].Tag()}, 627 {Tag: "machine-42"}, 628 {Tag: "unit-foo-0"}, 629 {Tag: "service-bar"}, 630 }} 631 result, err := s.provisioner.InstanceId(args) 632 c.Assert(err, gc.IsNil) 633 c.Assert(result, gc.DeepEquals, params.StringResults{ 634 Results: []params.StringResult{ 635 {Result: "i-am"}, 636 {Result: "i-am-not"}, 637 {Error: apiservertesting.NotProvisionedError("2")}, 638 {Error: apiservertesting.NotFoundError("machine 42")}, 639 {Error: apiservertesting.ErrUnauthorized}, 640 {Error: apiservertesting.ErrUnauthorized}, 641 }, 642 }) 643 } 644 645 func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) { 646 c.Assert(s.resources.Count(), gc.Equals, 0) 647 648 result, err := s.provisioner.WatchEnvironMachines() 649 c.Assert(err, gc.IsNil) 650 c.Assert(result, gc.DeepEquals, params.StringsWatchResult{ 651 StringsWatcherId: "1", 652 Changes: []string{"0", "1", "2"}, 653 }) 654 655 // Verify the resources were registered and stop them when done. 656 c.Assert(s.resources.Count(), gc.Equals, 1) 657 resource := s.resources.Get("1") 658 defer statetesting.AssertStop(c, resource) 659 660 // Check that the Watch has consumed the initial event ("returned" 661 // in the Watch call) 662 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 663 wc.AssertNoChange() 664 665 // Make sure WatchEnvironMachines fails with a machine agent login. 666 anAuthorizer := s.authorizer 667 anAuthorizer.MachineAgent = true 668 anAuthorizer.EnvironManager = false 669 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 670 c.Assert(err, gc.IsNil) 671 672 result, err = aProvisioner.WatchEnvironMachines() 673 c.Assert(err, gc.ErrorMatches, "permission denied") 674 c.Assert(result, gc.DeepEquals, params.StringsWatchResult{}) 675 } 676 677 func (s *withoutStateServerSuite) TestToolsNothing(c *gc.C) { 678 // Not an error to watch nothing 679 results, err := s.provisioner.Tools(params.Entities{}) 680 c.Assert(err, gc.IsNil) 681 c.Check(results.Results, gc.HasLen, 0) 682 } 683 684 func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) { 685 cfg, err := s.State.EnvironConfig() 686 c.Assert(err, gc.IsNil) 687 newCfg, err := cfg.Apply(map[string]interface{}{ 688 "http-proxy": "http://proxy.example.com:9000", 689 }) 690 c.Assert(err, gc.IsNil) 691 err = s.State.SetEnvironConfig(newCfg, cfg) 692 c.Assert(err, gc.IsNil) 693 expectedProxy := osenv.ProxySettings{ 694 Http: "http://proxy.example.com:9000", 695 } 696 697 results, err := s.provisioner.ContainerConfig() 698 c.Check(err, gc.IsNil) 699 c.Check(results.ProviderType, gc.Equals, "dummy") 700 c.Check(results.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) 701 c.Check(results.SSLHostnameVerification, jc.IsTrue) 702 c.Check(results.SyslogPort, gc.Equals, 2345) 703 c.Check(results.Proxy, gc.DeepEquals, expectedProxy) 704 c.Check(results.AptProxy, gc.DeepEquals, expectedProxy) 705 } 706 707 func (s *withoutStateServerSuite) TestToolsRefusesWrongAgent(c *gc.C) { 708 anAuthorizer := s.authorizer 709 anAuthorizer.Tag = "machine-12354" 710 anAuthorizer.EnvironManager = false 711 anAuthorizer.MachineAgent = true 712 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 713 c.Check(err, gc.IsNil) 714 args := params.Entities{ 715 Entities: []params.Entity{{Tag: s.machines[0].Tag()}}, 716 } 717 results, err := aProvisioner.Tools(args) 718 // It is not an error to make the request, but the specific item is rejected 719 c.Assert(err, gc.IsNil) 720 c.Check(results.Results, gc.HasLen, 1) 721 toolResult := results.Results[0] 722 c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 723 } 724 725 func (s *withoutStateServerSuite) TestToolsForAgent(c *gc.C) { 726 cur := version.Current 727 agent := params.Entity{Tag: s.machines[0].Tag()} 728 729 // The machine must have its existing tools set before we query for the 730 // next tools. This is so that we can grab Arch and Series without 731 // having to pass it in again 732 err := s.machines[0].SetAgentVersion(version.Current) 733 c.Assert(err, gc.IsNil) 734 735 args := params.Entities{Entities: []params.Entity{agent}} 736 results, err := s.provisioner.Tools(args) 737 c.Assert(err, gc.IsNil) 738 c.Check(results.Results, gc.HasLen, 1) 739 c.Assert(results.Results[0].Error, gc.IsNil) 740 agentTools := results.Results[0].Tools 741 c.Check(agentTools.URL, gc.Not(gc.Equals), "") 742 c.Check(agentTools.Version, gc.DeepEquals, cur) 743 } 744 745 func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) { 746 args := params.MachineContainersParams{ 747 Params: []params.MachineContainers{ 748 { 749 MachineTag: "machine-0", 750 ContainerTypes: []instance.ContainerType{instance.LXC}, 751 }, 752 { 753 MachineTag: "machine-1", 754 ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM}, 755 }, 756 }, 757 } 758 results, err := s.provisioner.SetSupportedContainers(args) 759 c.Assert(err, gc.IsNil) 760 c.Assert(results.Results, gc.HasLen, 2) 761 for _, result := range results.Results { 762 c.Assert(result.Error, gc.IsNil) 763 } 764 m0, err := s.State.Machine("0") 765 c.Assert(err, gc.IsNil) 766 containers, ok := m0.SupportedContainers() 767 c.Assert(ok, jc.IsTrue) 768 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC}) 769 m1, err := s.State.Machine("1") 770 c.Assert(err, gc.IsNil) 771 containers, ok = m1.SupportedContainers() 772 c.Assert(ok, jc.IsTrue) 773 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 774 } 775 776 func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) { 777 // Login as a machine agent for machine 0. 778 anAuthorizer := s.authorizer 779 anAuthorizer.MachineAgent = true 780 anAuthorizer.EnvironManager = false 781 anAuthorizer.Tag = s.machines[0].Tag() 782 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 783 c.Assert(err, gc.IsNil) 784 c.Assert(aProvisioner, gc.NotNil) 785 786 args := params.MachineContainersParams{ 787 Params: []params.MachineContainers{{ 788 MachineTag: "machine-0", 789 ContainerTypes: []instance.ContainerType{instance.LXC}, 790 }, { 791 MachineTag: "machine-1", 792 ContainerTypes: []instance.ContainerType{instance.LXC}, 793 }, { 794 MachineTag: "machine-42", 795 ContainerTypes: []instance.ContainerType{instance.LXC}, 796 }, 797 }, 798 } 799 // Only machine 0 can have it's containers updated. 800 results, err := aProvisioner.SetSupportedContainers(args) 801 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 802 Results: []params.ErrorResult{ 803 {Error: nil}, 804 {Error: apiservertesting.ErrUnauthorized}, 805 {Error: apiservertesting.ErrUnauthorized}, 806 }, 807 }) 808 } 809 810 func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) { 811 args := params.MachineContainersParams{ 812 Params: []params.MachineContainers{ 813 { 814 MachineTag: "machine-0", 815 }, 816 }, 817 } 818 results, err := s.provisioner.SetSupportedContainers(args) 819 c.Assert(err, gc.IsNil) 820 c.Assert(results.Results, gc.HasLen, 1) 821 c.Assert(results.Results[0].Error, gc.IsNil) 822 m0, err := s.State.Machine("0") 823 c.Assert(err, gc.IsNil) 824 containers, ok := m0.SupportedContainers() 825 c.Assert(ok, jc.IsTrue) 826 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 827 } 828 829 var _ = gc.Suite(&withStateServerSuite{}) 830 831 type withStateServerSuite struct { 832 provisionerSuite 833 } 834 835 func (s *withStateServerSuite) SetUpTest(c *gc.C) { 836 s.provisionerSuite.setUpTest(c, true) 837 } 838 839 func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) { 840 addrs, err := s.State.APIAddresses() 841 c.Assert(err, gc.IsNil) 842 843 result, err := s.provisioner.APIAddresses() 844 c.Assert(err, gc.IsNil) 845 c.Assert(result, gc.DeepEquals, params.StringsResult{ 846 Result: addrs, 847 }) 848 } 849 850 func (s *withStateServerSuite) TestStateAddresses(c *gc.C) { 851 addresses, err := s.State.Addresses() 852 c.Assert(err, gc.IsNil) 853 854 result, err := s.provisioner.StateAddresses() 855 c.Assert(err, gc.IsNil) 856 c.Assert(result, gc.DeepEquals, params.StringsResult{ 857 Result: addresses, 858 }) 859 } 860 861 func (s *withStateServerSuite) TestCACert(c *gc.C) { 862 result := s.provisioner.CACert() 863 c.Assert(result, gc.DeepEquals, params.BytesResult{ 864 Result: s.State.CACert(), 865 }) 866 }