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