github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/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 "github.com/juju/errors" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils/proxy" 14 gc "launchpad.net/gocheck" 15 16 "github.com/juju/juju/constraints" 17 "github.com/juju/juju/container" 18 "github.com/juju/juju/instance" 19 "github.com/juju/juju/juju/testing" 20 "github.com/juju/juju/network" 21 "github.com/juju/juju/state" 22 "github.com/juju/juju/state/api/params" 23 "github.com/juju/juju/state/apiserver/common" 24 commontesting "github.com/juju/juju/state/apiserver/common/testing" 25 "github.com/juju/juju/state/apiserver/provisioner" 26 apiservertesting "github.com/juju/juju/state/apiserver/testing" 27 statetesting "github.com/juju/juju/state/testing" 28 coretesting "github.com/juju/juju/testing" 29 "github.com/juju/juju/version" 30 ) 31 32 func Test(t *stdtesting.T) { 33 coretesting.MgoTestPackage(t) 34 } 35 36 type provisionerSuite struct { 37 testing.JujuConnSuite 38 39 machines []*state.Machine 40 41 authorizer apiservertesting.FakeAuthorizer 42 resources *common.Resources 43 provisioner *provisioner.ProvisionerAPI 44 } 45 46 var _ = gc.Suite(&provisionerSuite{}) 47 48 func (s *provisionerSuite) SetUpTest(c *gc.C) { 49 s.setUpTest(c, false) 50 } 51 52 func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) { 53 s.JujuConnSuite.SetUpTest(c) 54 55 // Reset previous machines (if any) and create 3 machines 56 // for the tests, plus an optional state server machine. 57 s.machines = nil 58 // Note that the specific machine ids allocated are assumed 59 // to be numerically consecutive from zero. 60 if withStateServer { 61 s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State)) 62 } 63 for i := 0; i < 5; i++ { 64 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 65 c.Check(err, gc.IsNil) 66 s.machines = append(s.machines, machine) 67 } 68 69 // Create a FakeAuthorizer so we can check permissions, 70 // set up assuming we logged in as the environment manager. 71 s.authorizer = apiservertesting.FakeAuthorizer{ 72 LoggedIn: true, 73 EnvironManager: true, 74 } 75 76 // Create the resource registry separately to track invocations to 77 // Register. 78 s.resources = common.NewResources() 79 80 // Create a provisioner API for the machine. 81 provisionerAPI, err := provisioner.NewProvisionerAPI( 82 s.State, 83 s.resources, 84 s.authorizer, 85 ) 86 c.Assert(err, gc.IsNil) 87 s.provisioner = provisionerAPI 88 } 89 90 type withoutStateServerSuite struct { 91 provisionerSuite 92 *commontesting.EnvironWatcherTest 93 } 94 95 var _ = gc.Suite(&withoutStateServerSuite{}) 96 97 func (s *withoutStateServerSuite) SetUpTest(c *gc.C) { 98 s.setUpTest(c, false) 99 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets) 100 } 101 102 func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) { 103 anAuthorizer := s.authorizer 104 anAuthorizer.MachineAgent = false 105 anAuthorizer.EnvironManager = true 106 // Works with an environment manager, which is not a machine agent. 107 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 108 c.Assert(err, gc.IsNil) 109 c.Assert(aProvisioner, gc.NotNil) 110 111 // But fails with neither a machine agent or an environment manager. 112 anAuthorizer.EnvironManager = false 113 aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 114 c.Assert(err, gc.NotNil) 115 c.Assert(aProvisioner, gc.IsNil) 116 c.Assert(err, gc.ErrorMatches, "permission denied") 117 } 118 119 func (s *withoutStateServerSuite) TestSetPasswords(c *gc.C) { 120 args := params.EntityPasswords{ 121 Changes: []params.EntityPassword{ 122 {Tag: s.machines[0].Tag(), Password: "xxx0-1234567890123457890"}, 123 {Tag: s.machines[1].Tag(), Password: "xxx1-1234567890123457890"}, 124 {Tag: s.machines[2].Tag(), Password: "xxx2-1234567890123457890"}, 125 {Tag: s.machines[3].Tag(), Password: "xxx3-1234567890123457890"}, 126 {Tag: s.machines[4].Tag(), Password: "xxx4-1234567890123457890"}, 127 {Tag: "machine-42", Password: "foo"}, 128 {Tag: "unit-foo-0", Password: "zzz"}, 129 {Tag: "service-bar", Password: "abc"}, 130 }, 131 } 132 results, err := s.provisioner.SetPasswords(args) 133 c.Assert(err, gc.IsNil) 134 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 135 Results: []params.ErrorResult{ 136 {nil}, 137 {nil}, 138 {nil}, 139 {nil}, 140 {nil}, 141 {apiservertesting.NotFoundError("machine 42")}, 142 {apiservertesting.ErrUnauthorized}, 143 {apiservertesting.ErrUnauthorized}, 144 }, 145 }) 146 147 // Verify the changes to both machines succeeded. 148 for i, machine := range s.machines { 149 c.Logf("trying %q password", machine.Tag()) 150 err = machine.Refresh() 151 c.Assert(err, gc.IsNil) 152 changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i)) 153 c.Assert(changed, jc.IsTrue) 154 } 155 } 156 157 func (s *withoutStateServerSuite) TestShortSetPasswords(c *gc.C) { 158 args := params.EntityPasswords{ 159 Changes: []params.EntityPassword{ 160 {Tag: s.machines[1].Tag(), Password: "xxx1"}, 161 }, 162 } 163 results, err := s.provisioner.SetPasswords(args) 164 c.Assert(err, gc.IsNil) 165 c.Assert(results.Results, gc.HasLen, 1) 166 c.Assert(results.Results[0].Error, gc.ErrorMatches, 167 "password is only 4 bytes long, and is not a valid Agent password") 168 } 169 170 func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) { 171 // NOTE: This and the next call serve to test the two 172 // different authorization schemes: 173 // 1. Machine agents can access their own machine and 174 // any container that has their own machine as parent; 175 // 2. Environment managers can access any machine without 176 // a parent. 177 // There's no need to repeat this test for each method, 178 // because the authorization logic is common. 179 180 // Login as a machine agent for machine 0. 181 anAuthorizer := s.authorizer 182 anAuthorizer.MachineAgent = true 183 anAuthorizer.EnvironManager = false 184 anAuthorizer.Tag = s.machines[0].Tag() 185 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 186 c.Assert(err, gc.IsNil) 187 c.Assert(aProvisioner, gc.NotNil) 188 189 // Make the machine dead before trying to add containers. 190 err = s.machines[0].EnsureDead() 191 c.Assert(err, gc.IsNil) 192 193 // Create some containers to work on. 194 template := state.MachineTemplate{ 195 Series: "quantal", 196 Jobs: []state.MachineJob{state.JobHostUnits}, 197 } 198 var containers []*state.Machine 199 for i := 0; i < 3; i++ { 200 container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC) 201 c.Check(err, gc.IsNil) 202 containers = append(containers, container) 203 } 204 // Make one container dead. 205 err = containers[1].EnsureDead() 206 c.Assert(err, gc.IsNil) 207 208 args := params.Entities{Entities: []params.Entity{ 209 {Tag: s.machines[0].Tag()}, 210 {Tag: s.machines[1].Tag()}, 211 {Tag: containers[0].Tag()}, 212 {Tag: containers[1].Tag()}, 213 {Tag: containers[2].Tag()}, 214 {Tag: "machine-42"}, 215 {Tag: "unit-foo-0"}, 216 {Tag: "service-bar"}, 217 }} 218 result, err := aProvisioner.Life(args) 219 c.Assert(err, gc.IsNil) 220 c.Assert(result, gc.DeepEquals, params.LifeResults{ 221 Results: []params.LifeResult{ 222 {Life: "dead"}, 223 {Error: apiservertesting.ErrUnauthorized}, 224 {Life: "alive"}, 225 {Life: "dead"}, 226 {Life: "alive"}, 227 {Error: apiservertesting.ErrUnauthorized}, 228 {Error: apiservertesting.ErrUnauthorized}, 229 {Error: apiservertesting.ErrUnauthorized}, 230 }, 231 }) 232 } 233 234 func (s *withoutStateServerSuite) TestLifeAsEnvironManager(c *gc.C) { 235 err := s.machines[1].EnsureDead() 236 c.Assert(err, gc.IsNil) 237 err = s.machines[1].Refresh() 238 c.Assert(err, gc.IsNil) 239 c.Assert(s.machines[0].Life(), gc.Equals, state.Alive) 240 c.Assert(s.machines[1].Life(), gc.Equals, state.Dead) 241 c.Assert(s.machines[2].Life(), gc.Equals, state.Alive) 242 243 args := params.Entities{Entities: []params.Entity{ 244 {Tag: s.machines[0].Tag()}, 245 {Tag: s.machines[1].Tag()}, 246 {Tag: s.machines[2].Tag()}, 247 {Tag: "machine-42"}, 248 {Tag: "unit-foo-0"}, 249 {Tag: "service-bar"}, 250 }} 251 result, err := s.provisioner.Life(args) 252 c.Assert(err, gc.IsNil) 253 c.Assert(result, gc.DeepEquals, params.LifeResults{ 254 Results: []params.LifeResult{ 255 {Life: "alive"}, 256 {Life: "dead"}, 257 {Life: "alive"}, 258 {Error: apiservertesting.NotFoundError("machine 42")}, 259 {Error: apiservertesting.ErrUnauthorized}, 260 {Error: apiservertesting.ErrUnauthorized}, 261 }, 262 }) 263 264 // Remove the subordinate and make sure it's detected. 265 err = s.machines[1].Remove() 266 c.Assert(err, gc.IsNil) 267 err = s.machines[1].Refresh() 268 c.Assert(err, jc.Satisfies, errors.IsNotFound) 269 270 result, err = s.provisioner.Life(params.Entities{ 271 Entities: []params.Entity{ 272 {Tag: s.machines[1].Tag()}, 273 }, 274 }) 275 c.Assert(err, gc.IsNil) 276 c.Assert(result, gc.DeepEquals, params.LifeResults{ 277 Results: []params.LifeResult{ 278 {Error: apiservertesting.NotFoundError("machine 1")}, 279 }, 280 }) 281 } 282 283 func (s *withoutStateServerSuite) TestRemove(c *gc.C) { 284 err := s.machines[1].EnsureDead() 285 c.Assert(err, gc.IsNil) 286 s.assertLife(c, 0, state.Alive) 287 s.assertLife(c, 1, state.Dead) 288 s.assertLife(c, 2, state.Alive) 289 290 args := params.Entities{Entities: []params.Entity{ 291 {Tag: s.machines[0].Tag()}, 292 {Tag: s.machines[1].Tag()}, 293 {Tag: s.machines[2].Tag()}, 294 {Tag: "machine-42"}, 295 {Tag: "unit-foo-0"}, 296 {Tag: "service-bar"}, 297 }} 298 result, err := s.provisioner.Remove(args) 299 c.Assert(err, gc.IsNil) 300 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 301 Results: []params.ErrorResult{ 302 {¶ms.Error{Message: `cannot remove entity "machine-0": still alive`}}, 303 {nil}, 304 {¶ms.Error{Message: `cannot remove entity "machine-2": still alive`}}, 305 {apiservertesting.NotFoundError("machine 42")}, 306 {apiservertesting.ErrUnauthorized}, 307 {apiservertesting.ErrUnauthorized}, 308 }, 309 }) 310 311 // Verify the changes. 312 s.assertLife(c, 0, state.Alive) 313 err = s.machines[1].Refresh() 314 c.Assert(err, jc.Satisfies, errors.IsNotFound) 315 s.assertLife(c, 2, state.Alive) 316 } 317 318 func (s *withoutStateServerSuite) TestSetStatus(c *gc.C) { 319 err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 320 c.Assert(err, gc.IsNil) 321 err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil) 322 c.Assert(err, gc.IsNil) 323 err = s.machines[2].SetStatus(params.StatusError, "not really", nil) 324 c.Assert(err, gc.IsNil) 325 326 args := params.SetStatus{ 327 Entities: []params.EntityStatus{ 328 {Tag: s.machines[0].Tag(), Status: params.StatusError, Info: "not really", 329 Data: params.StatusData{"foo": "bar"}}, 330 {Tag: s.machines[1].Tag(), Status: params.StatusStopped, Info: "foobar"}, 331 {Tag: s.machines[2].Tag(), Status: params.StatusStarted, Info: "again"}, 332 {Tag: "machine-42", Status: params.StatusStarted, Info: "blah"}, 333 {Tag: "unit-foo-0", Status: params.StatusStopped, Info: "foobar"}, 334 {Tag: "service-bar", Status: params.StatusStopped, Info: "foobar"}, 335 }} 336 result, err := s.provisioner.SetStatus(args) 337 c.Assert(err, gc.IsNil) 338 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 339 Results: []params.ErrorResult{ 340 {nil}, 341 {nil}, 342 {nil}, 343 {apiservertesting.NotFoundError("machine 42")}, 344 {apiservertesting.ErrUnauthorized}, 345 {apiservertesting.ErrUnauthorized}, 346 }, 347 }) 348 349 // Verify the changes. 350 s.assertStatus(c, 0, params.StatusError, "not really", params.StatusData{"foo": "bar"}) 351 s.assertStatus(c, 1, params.StatusStopped, "foobar", params.StatusData{}) 352 s.assertStatus(c, 2, params.StatusStarted, "again", params.StatusData{}) 353 } 354 355 func (s *withoutStateServerSuite) TestMachinesWithTransientErrors(c *gc.C) { 356 err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 357 c.Assert(err, gc.IsNil) 358 err = s.machines[1].SetStatus(params.StatusError, "transient error", 359 params.StatusData{"transient": true, "foo": "bar"}) 360 c.Assert(err, gc.IsNil) 361 err = s.machines[2].SetStatus(params.StatusError, "error", params.StatusData{"transient": false}) 362 c.Assert(err, gc.IsNil) 363 err = s.machines[3].SetStatus(params.StatusError, "error", nil) 364 c.Assert(err, gc.IsNil) 365 // Machine 4 is provisioned but error not reset yet. 366 err = s.machines[4].SetStatus(params.StatusError, "transient error", 367 params.StatusData{"transient": true, "foo": "bar"}) 368 c.Assert(err, gc.IsNil) 369 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 370 err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars) 371 c.Assert(err, gc.IsNil) 372 373 result, err := s.provisioner.MachinesWithTransientErrors() 374 c.Assert(err, gc.IsNil) 375 c.Assert(result, gc.DeepEquals, params.StatusResults{ 376 Results: []params.StatusResult{ 377 {Id: "1", Life: "alive", Status: "error", Info: "transient error", 378 Data: params.StatusData{"transient": true, "foo": "bar"}}, 379 }, 380 }) 381 } 382 383 func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) { 384 // Machines where there's permission issues are omitted. 385 anAuthorizer := s.authorizer 386 anAuthorizer.MachineAgent = true 387 anAuthorizer.EnvironManager = false 388 anAuthorizer.Tag = "machine-1" 389 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, 390 anAuthorizer) 391 err = s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 392 c.Assert(err, gc.IsNil) 393 err = s.machines[1].SetStatus(params.StatusError, "transient error", 394 params.StatusData{"transient": true, "foo": "bar"}) 395 c.Assert(err, gc.IsNil) 396 err = s.machines[2].SetStatus(params.StatusError, "error", params.StatusData{"transient": false}) 397 c.Assert(err, gc.IsNil) 398 err = s.machines[3].SetStatus(params.StatusError, "error", nil) 399 c.Assert(err, gc.IsNil) 400 401 result, err := aProvisioner.MachinesWithTransientErrors() 402 c.Assert(err, gc.IsNil) 403 c.Assert(result, gc.DeepEquals, params.StatusResults{ 404 Results: []params.StatusResult{ 405 {Id: "1", Life: "alive", Status: "error", Info: "transient error", 406 Data: params.StatusData{"transient": true, "foo": "bar"}}, 407 }, 408 }) 409 } 410 411 func (s *withoutStateServerSuite) TestEnsureDead(c *gc.C) { 412 err := s.machines[1].EnsureDead() 413 c.Assert(err, gc.IsNil) 414 s.assertLife(c, 0, state.Alive) 415 s.assertLife(c, 1, state.Dead) 416 s.assertLife(c, 2, state.Alive) 417 418 args := params.Entities{Entities: []params.Entity{ 419 {Tag: s.machines[0].Tag()}, 420 {Tag: s.machines[1].Tag()}, 421 {Tag: s.machines[2].Tag()}, 422 {Tag: "machine-42"}, 423 {Tag: "unit-foo-0"}, 424 {Tag: "service-bar"}, 425 }} 426 result, err := s.provisioner.EnsureDead(args) 427 c.Assert(err, gc.IsNil) 428 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 429 Results: []params.ErrorResult{ 430 {nil}, 431 {nil}, 432 {nil}, 433 {apiservertesting.NotFoundError("machine 42")}, 434 {apiservertesting.ErrUnauthorized}, 435 {apiservertesting.ErrUnauthorized}, 436 }, 437 }) 438 439 // Verify the changes. 440 s.assertLife(c, 0, state.Dead) 441 s.assertLife(c, 1, state.Dead) 442 s.assertLife(c, 2, state.Dead) 443 } 444 445 func (s *withoutStateServerSuite) assertLife(c *gc.C, index int, expectLife state.Life) { 446 err := s.machines[index].Refresh() 447 c.Assert(err, gc.IsNil) 448 c.Assert(s.machines[index].Life(), gc.Equals, expectLife) 449 } 450 451 func (s *withoutStateServerSuite) assertStatus(c *gc.C, index int, expectStatus params.Status, expectInfo string, 452 expectData params.StatusData) { 453 454 status, info, data, err := s.machines[index].Status() 455 c.Assert(err, gc.IsNil) 456 c.Assert(status, gc.Equals, expectStatus) 457 c.Assert(info, gc.Equals, expectInfo) 458 c.Assert(data, gc.DeepEquals, expectData) 459 } 460 461 func (s *withoutStateServerSuite) TestWatchContainers(c *gc.C) { 462 c.Assert(s.resources.Count(), gc.Equals, 0) 463 464 args := params.WatchContainers{Params: []params.WatchContainer{ 465 {MachineTag: s.machines[0].Tag(), ContainerType: string(instance.LXC)}, 466 {MachineTag: s.machines[1].Tag(), ContainerType: string(instance.KVM)}, 467 {MachineTag: "machine-42", ContainerType: ""}, 468 {MachineTag: "unit-foo-0", ContainerType: ""}, 469 {MachineTag: "service-bar", ContainerType: ""}, 470 }} 471 result, err := s.provisioner.WatchContainers(args) 472 c.Assert(err, gc.IsNil) 473 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 474 Results: []params.StringsWatchResult{ 475 {StringsWatcherId: "1", Changes: []string{}}, 476 {StringsWatcherId: "2", Changes: []string{}}, 477 {Error: apiservertesting.NotFoundError("machine 42")}, 478 {Error: apiservertesting.ErrUnauthorized}, 479 {Error: apiservertesting.ErrUnauthorized}, 480 }, 481 }) 482 483 // Verify the resources were registered and stop them when done. 484 c.Assert(s.resources.Count(), gc.Equals, 2) 485 m0Watcher := s.resources.Get("1") 486 defer statetesting.AssertStop(c, m0Watcher) 487 m1Watcher := s.resources.Get("2") 488 defer statetesting.AssertStop(c, m1Watcher) 489 490 // Check that the Watch has consumed the initial event ("returned" 491 // in the Watch call) 492 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 493 wc0.AssertNoChange() 494 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 495 wc1.AssertNoChange() 496 } 497 498 func (s *withoutStateServerSuite) TestWatchAllContainers(c *gc.C) { 499 c.Assert(s.resources.Count(), gc.Equals, 0) 500 501 args := params.WatchContainers{Params: []params.WatchContainer{ 502 {MachineTag: s.machines[0].Tag()}, 503 {MachineTag: s.machines[1].Tag()}, 504 {MachineTag: "machine-42"}, 505 {MachineTag: "unit-foo-0"}, 506 {MachineTag: "service-bar"}, 507 }} 508 result, err := s.provisioner.WatchAllContainers(args) 509 c.Assert(err, gc.IsNil) 510 c.Assert(result, gc.DeepEquals, params.StringsWatchResults{ 511 Results: []params.StringsWatchResult{ 512 {StringsWatcherId: "1", Changes: []string{}}, 513 {StringsWatcherId: "2", Changes: []string{}}, 514 {Error: apiservertesting.NotFoundError("machine 42")}, 515 {Error: apiservertesting.ErrUnauthorized}, 516 {Error: apiservertesting.ErrUnauthorized}, 517 }, 518 }) 519 520 // Verify the resources were registered and stop them when done. 521 c.Assert(s.resources.Count(), gc.Equals, 2) 522 m0Watcher := s.resources.Get("1") 523 defer statetesting.AssertStop(c, m0Watcher) 524 m1Watcher := s.resources.Get("2") 525 defer statetesting.AssertStop(c, m1Watcher) 526 527 // Check that the Watch has consumed the initial event ("returned" 528 // in the Watch call) 529 wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher)) 530 wc0.AssertNoChange() 531 wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher)) 532 wc1.AssertNoChange() 533 } 534 535 func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) { 536 // Now test it with a non-environment manager and make sure 537 // the secret attributes are masked. 538 anAuthorizer := s.authorizer 539 anAuthorizer.MachineAgent = true 540 anAuthorizer.EnvironManager = false 541 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, 542 anAuthorizer) 543 c.Assert(err, gc.IsNil) 544 s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets) 545 } 546 547 func (s *withoutStateServerSuite) TestStatus(c *gc.C) { 548 err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) 549 c.Assert(err, gc.IsNil) 550 err = s.machines[1].SetStatus(params.StatusStopped, "foo", nil) 551 c.Assert(err, gc.IsNil) 552 err = s.machines[2].SetStatus(params.StatusError, "not really", params.StatusData{"foo": "bar"}) 553 c.Assert(err, gc.IsNil) 554 555 args := params.Entities{Entities: []params.Entity{ 556 {Tag: s.machines[0].Tag()}, 557 {Tag: s.machines[1].Tag()}, 558 {Tag: s.machines[2].Tag()}, 559 {Tag: "machine-42"}, 560 {Tag: "unit-foo-0"}, 561 {Tag: "service-bar"}, 562 }} 563 result, err := s.provisioner.Status(args) 564 c.Assert(err, gc.IsNil) 565 c.Assert(result, gc.DeepEquals, params.StatusResults{ 566 Results: []params.StatusResult{ 567 {Status: params.StatusStarted, Info: "blah", Data: params.StatusData{}}, 568 {Status: params.StatusStopped, Info: "foo", Data: params.StatusData{}}, 569 {Status: params.StatusError, Info: "not really", Data: params.StatusData{"foo": "bar"}}, 570 {Error: apiservertesting.NotFoundError("machine 42")}, 571 {Error: apiservertesting.ErrUnauthorized}, 572 {Error: apiservertesting.ErrUnauthorized}, 573 }, 574 }) 575 } 576 577 func (s *withoutStateServerSuite) TestSeries(c *gc.C) { 578 // Add a machine with different series. 579 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 580 c.Assert(err, gc.IsNil) 581 582 args := params.Entities{Entities: []params.Entity{ 583 {Tag: s.machines[0].Tag()}, 584 {Tag: foobarMachine.Tag()}, 585 {Tag: s.machines[2].Tag()}, 586 {Tag: "machine-42"}, 587 {Tag: "unit-foo-0"}, 588 {Tag: "service-bar"}, 589 }} 590 result, err := s.provisioner.Series(args) 591 c.Assert(err, gc.IsNil) 592 c.Assert(result, gc.DeepEquals, params.StringResults{ 593 Results: []params.StringResult{ 594 {Result: s.machines[0].Series()}, 595 {Result: foobarMachine.Series()}, 596 {Result: s.machines[2].Series()}, 597 {Error: apiservertesting.NotFoundError("machine 42")}, 598 {Error: apiservertesting.ErrUnauthorized}, 599 {Error: apiservertesting.ErrUnauthorized}, 600 }, 601 }) 602 } 603 604 func (s *withoutStateServerSuite) TestDistributionGroup(c *gc.C) { 605 addUnits := func(name string, machines ...*state.Machine) (units []*state.Unit) { 606 svc := s.AddTestingService(c, name, s.AddTestingCharm(c, name)) 607 for _, m := range machines { 608 unit, err := svc.AddUnit() 609 c.Assert(err, gc.IsNil) 610 err = unit.AssignToMachine(m) 611 c.Assert(err, gc.IsNil) 612 units = append(units, unit) 613 } 614 return units 615 } 616 setProvisioned := func(id string) { 617 m, err := s.State.Machine(id) 618 c.Assert(err, gc.IsNil) 619 err = m.SetProvisioned(instance.Id("machine-"+id+"-inst"), "nonce", nil) 620 c.Assert(err, gc.IsNil) 621 } 622 623 mysqlUnit := addUnits("mysql", s.machines[0], s.machines[3])[0] 624 wordpressUnits := addUnits("wordpress", s.machines[0], s.machines[1], s.machines[2]) 625 626 // Unassign wordpress/1 from machine-1. 627 // The unit should not show up in the results. 628 err := wordpressUnits[1].UnassignFromMachine() 629 c.Assert(err, gc.IsNil) 630 631 // Provision machines 1, 2 and 3. Machine-0 remains 632 // unprovisioned, and machine-1 has no units, and so 633 // neither will show up in the results. 634 setProvisioned("1") 635 setProvisioned("2") 636 setProvisioned("3") 637 638 // Add a few state servers, provision two of them. 639 err = s.State.EnsureAvailability(3, constraints.Value{}, "quantal") 640 c.Assert(err, gc.IsNil) 641 setProvisioned("5") 642 setProvisioned("7") 643 644 // Create a logging service, subordinate to mysql. 645 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 646 eps, err := s.State.InferEndpoints([]string{"mysql", "logging"}) 647 c.Assert(err, gc.IsNil) 648 rel, err := s.State.AddRelation(eps...) 649 c.Assert(err, gc.IsNil) 650 ru, err := rel.Unit(mysqlUnit) 651 c.Assert(err, gc.IsNil) 652 err = ru.EnterScope(nil) 653 c.Assert(err, gc.IsNil) 654 655 args := params.Entities{Entities: []params.Entity{ 656 {Tag: s.machines[0].Tag()}, 657 {Tag: s.machines[1].Tag()}, 658 {Tag: s.machines[2].Tag()}, 659 {Tag: s.machines[3].Tag()}, 660 {Tag: "machine-5"}, 661 }} 662 result, err := s.provisioner.DistributionGroup(args) 663 c.Assert(err, gc.IsNil) 664 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 665 Results: []params.DistributionGroupResult{ 666 {Result: []instance.Id{"machine-2-inst", "machine-3-inst"}}, 667 {Result: []instance.Id{}}, 668 {Result: []instance.Id{"machine-2-inst"}}, 669 {Result: []instance.Id{"machine-3-inst"}}, 670 {Result: []instance.Id{"machine-5-inst", "machine-7-inst"}}, 671 }, 672 }) 673 } 674 675 func (s *withoutStateServerSuite) TestDistributionGroupEnvironManagerAuth(c *gc.C) { 676 args := params.Entities{Entities: []params.Entity{ 677 {Tag: "machine-0"}, 678 {Tag: "machine-42"}, 679 {Tag: "machine-0-lxc-99"}, 680 {Tag: "unit-foo-0"}, 681 {Tag: "service-bar"}, 682 }} 683 result, err := s.provisioner.DistributionGroup(args) 684 c.Assert(err, gc.IsNil) 685 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 686 Results: []params.DistributionGroupResult{ 687 // environ manager may access any top-level machines. 688 {Result: []instance.Id{}}, 689 {Error: apiservertesting.NotFoundError("machine 42")}, 690 // only a machine agent for the container or its 691 // parent may access it. 692 {Error: apiservertesting.ErrUnauthorized}, 693 // non-machines always unauthorized 694 {Error: apiservertesting.ErrUnauthorized}, 695 {Error: apiservertesting.ErrUnauthorized}, 696 }, 697 }) 698 } 699 700 func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) { 701 anAuthorizer := s.authorizer 702 anAuthorizer.Tag = "machine-1" 703 anAuthorizer.EnvironManager = false 704 anAuthorizer.MachineAgent = true 705 provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 706 c.Check(err, gc.IsNil) 707 args := params.Entities{Entities: []params.Entity{ 708 {Tag: "machine-0"}, 709 {Tag: "machine-1"}, 710 {Tag: "machine-42"}, 711 {Tag: "machine-0-lxc-99"}, 712 {Tag: "machine-1-lxc-99"}, 713 {Tag: "machine-1-lxc-99-lxc-100"}, 714 }} 715 result, err := provisioner.DistributionGroup(args) 716 c.Assert(err, gc.IsNil) 717 c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ 718 Results: []params.DistributionGroupResult{ 719 {Error: apiservertesting.ErrUnauthorized}, 720 {Result: []instance.Id{}}, 721 {Error: apiservertesting.ErrUnauthorized}, 722 // only a machine agent for the container or its 723 // parent may access it. 724 {Error: apiservertesting.ErrUnauthorized}, 725 {Error: apiservertesting.NotFoundError("machine 1/lxc/99")}, 726 {Error: apiservertesting.ErrUnauthorized}, 727 }, 728 }) 729 } 730 731 func (s *withoutStateServerSuite) TestProvisioningInfo(c *gc.C) { 732 cons := constraints.MustParse("cpu-cores=123 mem=8G networks=^net3,^net4") 733 template := state.MachineTemplate{ 734 Series: "quantal", 735 Jobs: []state.MachineJob{state.JobHostUnits}, 736 Constraints: cons, 737 Placement: "valid", 738 RequestedNetworks: []string{"net1", "net2"}, 739 } 740 placementMachine, err := s.State.AddOneMachine(template) 741 c.Assert(err, gc.IsNil) 742 743 args := params.Entities{Entities: []params.Entity{ 744 {Tag: s.machines[0].Tag()}, 745 {Tag: placementMachine.Tag()}, 746 {Tag: "machine-42"}, 747 {Tag: "unit-foo-0"}, 748 {Tag: "service-bar"}, 749 }} 750 result, err := s.provisioner.ProvisioningInfo(args) 751 c.Assert(err, gc.IsNil) 752 c.Assert(result, gc.DeepEquals, params.ProvisioningInfoResults{ 753 Results: []params.ProvisioningInfoResult{ 754 {Result: ¶ms.ProvisioningInfo{ 755 Series: "quantal", 756 Networks: []string{}, 757 }}, 758 {Result: ¶ms.ProvisioningInfo{ 759 Series: "quantal", 760 Constraints: template.Constraints, 761 Placement: template.Placement, 762 Networks: template.RequestedNetworks, 763 }}, 764 {Error: apiservertesting.NotFoundError("machine 42")}, 765 {Error: apiservertesting.ErrUnauthorized}, 766 {Error: apiservertesting.ErrUnauthorized}, 767 }, 768 }) 769 } 770 771 func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) { 772 // Login as a machine agent for machine 0. 773 anAuthorizer := s.authorizer 774 anAuthorizer.MachineAgent = true 775 anAuthorizer.EnvironManager = false 776 anAuthorizer.Tag = s.machines[0].Tag() 777 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 778 c.Assert(err, gc.IsNil) 779 c.Assert(aProvisioner, gc.NotNil) 780 781 args := params.Entities{Entities: []params.Entity{ 782 {Tag: s.machines[0].Tag()}, 783 {Tag: s.machines[0].Tag() + "-lxc-0"}, 784 {Tag: "machine-42"}, 785 {Tag: s.machines[1].Tag()}, 786 {Tag: "service-bar"}, 787 }} 788 789 // Only machine 0 and containers therein can be accessed. 790 results, err := aProvisioner.ProvisioningInfo(args) 791 c.Assert(results, gc.DeepEquals, params.ProvisioningInfoResults{ 792 Results: []params.ProvisioningInfoResult{ 793 {Result: ¶ms.ProvisioningInfo{ 794 Series: "quantal", 795 Networks: []string{}, 796 }}, 797 {Error: apiservertesting.NotFoundError("machine 0/lxc/0")}, 798 {Error: apiservertesting.ErrUnauthorized}, 799 {Error: apiservertesting.ErrUnauthorized}, 800 {Error: apiservertesting.ErrUnauthorized}, 801 }, 802 }) 803 } 804 805 func (s *withoutStateServerSuite) TestConstraints(c *gc.C) { 806 // Add a machine with some constraints. 807 cons := constraints.MustParse("cpu-cores=123", "mem=8G", "networks=net3,^net4") 808 template := state.MachineTemplate{ 809 Series: "quantal", 810 Jobs: []state.MachineJob{state.JobHostUnits}, 811 Constraints: cons, 812 } 813 consMachine, err := s.State.AddOneMachine(template) 814 c.Assert(err, gc.IsNil) 815 816 machine0Constraints, err := s.machines[0].Constraints() 817 c.Assert(err, gc.IsNil) 818 819 args := params.Entities{Entities: []params.Entity{ 820 {Tag: s.machines[0].Tag()}, 821 {Tag: consMachine.Tag()}, 822 {Tag: "machine-42"}, 823 {Tag: "unit-foo-0"}, 824 {Tag: "service-bar"}, 825 }} 826 result, err := s.provisioner.Constraints(args) 827 c.Assert(err, gc.IsNil) 828 c.Assert(result, gc.DeepEquals, params.ConstraintsResults{ 829 Results: []params.ConstraintsResult{ 830 {Constraints: machine0Constraints}, 831 {Constraints: template.Constraints}, 832 {Error: apiservertesting.NotFoundError("machine 42")}, 833 {Error: apiservertesting.ErrUnauthorized}, 834 {Error: apiservertesting.ErrUnauthorized}, 835 }, 836 }) 837 } 838 839 func (s *withoutStateServerSuite) TestRequestedNetworks(c *gc.C) { 840 // Add a machine with some requested networks. 841 template := state.MachineTemplate{ 842 Series: "quantal", 843 Jobs: []state.MachineJob{state.JobHostUnits}, 844 RequestedNetworks: []string{"net1", "net2"}, 845 } 846 netsMachine, err := s.State.AddOneMachine(template) 847 c.Assert(err, gc.IsNil) 848 849 networksMachine0, err := s.machines[0].RequestedNetworks() 850 c.Assert(err, gc.IsNil) 851 852 args := params.Entities{Entities: []params.Entity{ 853 {Tag: s.machines[0].Tag()}, 854 {Tag: netsMachine.Tag()}, 855 {Tag: "machine-42"}, 856 {Tag: "unit-foo-0"}, 857 {Tag: "service-bar"}, 858 }} 859 result, err := s.provisioner.RequestedNetworks(args) 860 c.Assert(err, gc.IsNil) 861 c.Assert(result, gc.DeepEquals, params.RequestedNetworksResults{ 862 Results: []params.RequestedNetworkResult{ 863 { 864 Networks: networksMachine0, 865 }, 866 { 867 Networks: template.RequestedNetworks, 868 }, 869 {Error: apiservertesting.NotFoundError("machine 42")}, 870 {Error: apiservertesting.ErrUnauthorized}, 871 {Error: apiservertesting.ErrUnauthorized}, 872 }, 873 }) 874 } 875 876 func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) { 877 // Provision machine 0 first. 878 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 879 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars) 880 c.Assert(err, gc.IsNil) 881 882 args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{ 883 {Tag: s.machines[0].Tag(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil}, 884 {Tag: s.machines[1].Tag(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars}, 885 {Tag: s.machines[2].Tag(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil}, 886 {Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil}, 887 {Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil}, 888 {Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil}, 889 }} 890 result, err := s.provisioner.SetProvisioned(args) 891 c.Assert(err, gc.IsNil) 892 c.Assert(result, gc.DeepEquals, params.ErrorResults{ 893 Results: []params.ErrorResult{ 894 {¶ms.Error{ 895 Message: `cannot set instance data for machine "0": already set`, 896 }}, 897 {nil}, 898 {nil}, 899 {apiservertesting.NotFoundError("machine 42")}, 900 {apiservertesting.ErrUnauthorized}, 901 {apiservertesting.ErrUnauthorized}, 902 }, 903 }) 904 905 // Verify machine 1 and 2 were provisioned. 906 c.Assert(s.machines[1].Refresh(), gc.IsNil) 907 c.Assert(s.machines[2].Refresh(), gc.IsNil) 908 909 instanceId, err := s.machines[1].InstanceId() 910 c.Assert(err, gc.IsNil) 911 c.Check(instanceId, gc.Equals, instance.Id("i-will")) 912 instanceId, err = s.machines[2].InstanceId() 913 c.Assert(err, gc.IsNil) 914 c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) 915 c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) 916 c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) 917 gotHardware, err := s.machines[1].HardwareCharacteristics() 918 c.Assert(err, gc.IsNil) 919 c.Check(gotHardware, gc.DeepEquals, &hwChars) 920 } 921 922 func (s *withoutStateServerSuite) TestSetInstanceInfo(c *gc.C) { 923 // Provision machine 0 first. 924 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 925 err := s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil) 926 c.Assert(err, gc.IsNil) 927 928 networks := []params.Network{{ 929 Tag: "network-net1", 930 ProviderId: "net1", 931 CIDR: "0.1.2.0/24", 932 VLANTag: 0, 933 }, { 934 Tag: "network-vlan42", 935 ProviderId: "vlan42", 936 CIDR: "0.2.2.0/24", 937 VLANTag: 42, 938 }, { 939 Tag: "network-vlan69", 940 ProviderId: "vlan69", 941 CIDR: "0.3.2.0/24", 942 VLANTag: 69, 943 }, { 944 Tag: "network-vlan42", // duplicated; ignored 945 ProviderId: "vlan42", 946 CIDR: "0.2.2.0/24", 947 VLANTag: 42, 948 }} 949 ifaces := []params.NetworkInterface{{ 950 MACAddress: "aa:bb:cc:dd:ee:f0", 951 NetworkTag: "network-net1", 952 InterfaceName: "eth0", 953 IsVirtual: false, 954 }, { 955 MACAddress: "aa:bb:cc:dd:ee:f1", 956 NetworkTag: "network-net1", 957 InterfaceName: "eth1", 958 IsVirtual: false, 959 }, { 960 MACAddress: "aa:bb:cc:dd:ee:f1", 961 NetworkTag: "network-vlan42", 962 InterfaceName: "eth1.42", 963 IsVirtual: true, 964 }, { 965 MACAddress: "aa:bb:cc:dd:ee:f0", 966 NetworkTag: "network-vlan69", 967 InterfaceName: "eth0.69", 968 IsVirtual: true, 969 }, { 970 MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored 971 NetworkTag: "network-vlan42", 972 InterfaceName: "eth2", 973 IsVirtual: true, 974 }, { 975 MACAddress: "aa:bb:cc:dd:ee:f2", 976 NetworkTag: "network-net1", 977 InterfaceName: "eth1", // duplicated name+machine id; ignored for machine 1. 978 IsVirtual: false, 979 }} 980 args := params.InstancesInfo{Machines: []params.InstanceInfo{{ 981 Tag: s.machines[0].Tag(), 982 InstanceId: "i-was", 983 Nonce: "fake_nonce", 984 }, { 985 Tag: s.machines[1].Tag(), 986 InstanceId: "i-will", 987 Nonce: "fake_nonce", 988 Characteristics: &hwChars, 989 Networks: networks, 990 Interfaces: ifaces, 991 }, { 992 Tag: s.machines[2].Tag(), 993 InstanceId: "i-am-too", 994 Nonce: "fake", 995 Characteristics: nil, 996 Networks: networks, 997 Interfaces: ifaces, 998 }, 999 {Tag: "machine-42"}, 1000 {Tag: "unit-foo-0"}, 1001 {Tag: "service-bar"}, 1002 }} 1003 result, err := s.provisioner.SetInstanceInfo(args) 1004 c.Assert(err, gc.IsNil) 1005 c.Assert(result, jc.DeepEquals, params.ErrorResults{ 1006 Results: []params.ErrorResult{ 1007 {¶ms.Error{ 1008 Message: `aborted instance "i-was": cannot set instance data for machine "0": already set`, 1009 }}, 1010 {nil}, 1011 {nil}, 1012 {apiservertesting.NotFoundError("machine 42")}, 1013 {apiservertesting.ErrUnauthorized}, 1014 {apiservertesting.ErrUnauthorized}, 1015 }, 1016 }) 1017 1018 // Verify machine 1 and 2 were provisioned. 1019 c.Assert(s.machines[1].Refresh(), gc.IsNil) 1020 c.Assert(s.machines[2].Refresh(), gc.IsNil) 1021 1022 instanceId, err := s.machines[1].InstanceId() 1023 c.Assert(err, gc.IsNil) 1024 c.Check(instanceId, gc.Equals, instance.Id("i-will")) 1025 instanceId, err = s.machines[2].InstanceId() 1026 c.Assert(err, gc.IsNil) 1027 c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) 1028 c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) 1029 c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) 1030 gotHardware, err := s.machines[1].HardwareCharacteristics() 1031 c.Assert(err, gc.IsNil) 1032 c.Check(gotHardware, gc.DeepEquals, &hwChars) 1033 ifacesMachine1, err := s.machines[1].NetworkInterfaces() 1034 c.Assert(err, gc.IsNil) 1035 c.Assert(ifacesMachine1, gc.HasLen, 4) 1036 actual := make([]params.NetworkInterface, len(ifacesMachine1)) 1037 for i, iface := range ifacesMachine1 { 1038 actual[i].InterfaceName = iface.InterfaceName() 1039 actual[i].NetworkTag = iface.NetworkTag() 1040 actual[i].MACAddress = iface.MACAddress() 1041 actual[i].IsVirtual = iface.IsVirtual() 1042 c.Check(iface.MachineId(), gc.Equals, s.machines[1].Id()) 1043 c.Check(iface.MachineTag(), gc.Equals, s.machines[1].Tag()) 1044 } 1045 c.Assert(actual, jc.SameContents, ifaces[:4]) 1046 ifacesMachine2, err := s.machines[2].NetworkInterfaces() 1047 c.Assert(err, gc.IsNil) 1048 c.Assert(ifacesMachine2, gc.HasLen, 1) 1049 c.Assert(ifacesMachine2[0].InterfaceName(), gc.Equals, ifaces[5].InterfaceName) 1050 c.Assert(ifacesMachine2[0].MACAddress(), gc.Equals, ifaces[5].MACAddress) 1051 c.Assert(ifacesMachine2[0].NetworkTag(), gc.Equals, ifaces[5].NetworkTag) 1052 c.Assert(ifacesMachine2[0].MachineId(), gc.Equals, s.machines[2].Id()) 1053 for i, _ := range networks { 1054 if i == 3 { 1055 // Last one was ignored, so don't check. 1056 break 1057 } 1058 tag, err := names.ParseTag(networks[i].Tag, names.NetworkTagKind) 1059 c.Assert(err, gc.IsNil) 1060 networkName := tag.Id() 1061 network, err := s.State.Network(networkName) 1062 c.Assert(err, gc.IsNil) 1063 c.Check(network.Name(), gc.Equals, networkName) 1064 c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) 1065 c.Check(network.Tag(), gc.Equals, networks[i].Tag) 1066 c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) 1067 c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) 1068 } 1069 } 1070 1071 func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) { 1072 // Provision 2 machines first. 1073 err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) 1074 c.Assert(err, gc.IsNil) 1075 hwChars := instance.MustParseHardware("arch=i386", "mem=4G") 1076 err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) 1077 c.Assert(err, gc.IsNil) 1078 1079 args := params.Entities{Entities: []params.Entity{ 1080 {Tag: s.machines[0].Tag()}, 1081 {Tag: s.machines[1].Tag()}, 1082 {Tag: s.machines[2].Tag()}, 1083 {Tag: "machine-42"}, 1084 {Tag: "unit-foo-0"}, 1085 {Tag: "service-bar"}, 1086 }} 1087 result, err := s.provisioner.InstanceId(args) 1088 c.Assert(err, gc.IsNil) 1089 c.Assert(result, gc.DeepEquals, params.StringResults{ 1090 Results: []params.StringResult{ 1091 {Result: "i-am"}, 1092 {Result: "i-am-not"}, 1093 {Error: apiservertesting.NotProvisionedError("2")}, 1094 {Error: apiservertesting.NotFoundError("machine 42")}, 1095 {Error: apiservertesting.ErrUnauthorized}, 1096 {Error: apiservertesting.ErrUnauthorized}, 1097 }, 1098 }) 1099 } 1100 1101 func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) { 1102 c.Assert(s.resources.Count(), gc.Equals, 0) 1103 1104 got, err := s.provisioner.WatchEnvironMachines() 1105 c.Assert(err, gc.IsNil) 1106 want := params.StringsWatchResult{ 1107 StringsWatcherId: "1", 1108 Changes: []string{"0", "1", "2", "3", "4"}, 1109 } 1110 c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) 1111 c.Assert(got.Changes, jc.SameContents, want.Changes) 1112 1113 // Verify the resources were registered and stop them when done. 1114 c.Assert(s.resources.Count(), gc.Equals, 1) 1115 resource := s.resources.Get("1") 1116 defer statetesting.AssertStop(c, resource) 1117 1118 // Check that the Watch has consumed the initial event ("returned" 1119 // in the Watch call) 1120 wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) 1121 wc.AssertNoChange() 1122 1123 // Make sure WatchEnvironMachines fails with a machine agent login. 1124 anAuthorizer := s.authorizer 1125 anAuthorizer.MachineAgent = true 1126 anAuthorizer.EnvironManager = false 1127 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1128 c.Assert(err, gc.IsNil) 1129 1130 result, err := aProvisioner.WatchEnvironMachines() 1131 c.Assert(err, gc.ErrorMatches, "permission denied") 1132 c.Assert(result, gc.DeepEquals, params.StringsWatchResult{}) 1133 } 1134 1135 func (s *withoutStateServerSuite) TestToolsNothing(c *gc.C) { 1136 // Not an error to watch nothing 1137 results, err := s.provisioner.Tools(params.Entities{}) 1138 c.Assert(err, gc.IsNil) 1139 c.Check(results.Results, gc.HasLen, 0) 1140 } 1141 1142 func (s *withoutStateServerSuite) TestContainerManagerConfig(c *gc.C) { 1143 args := params.ContainerManagerConfigParams{Type: instance.KVM} 1144 results, err := s.provisioner.ContainerManagerConfig(args) 1145 c.Check(err, gc.IsNil) 1146 c.Assert(results.ManagerConfig, gc.DeepEquals, map[string]string{ 1147 container.ConfigName: "juju", 1148 }) 1149 } 1150 1151 func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) { 1152 attrs := map[string]interface{}{ 1153 "http-proxy": "http://proxy.example.com:9000", 1154 } 1155 err := s.State.UpdateEnvironConfig(attrs, nil, nil) 1156 c.Assert(err, gc.IsNil) 1157 expectedProxy := proxy.Settings{ 1158 Http: "http://proxy.example.com:9000", 1159 } 1160 1161 results, err := s.provisioner.ContainerConfig() 1162 c.Check(err, gc.IsNil) 1163 c.Check(results.ProviderType, gc.Equals, "dummy") 1164 c.Check(results.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) 1165 c.Check(results.SSLHostnameVerification, jc.IsTrue) 1166 c.Check(results.Proxy, gc.DeepEquals, expectedProxy) 1167 c.Check(results.AptProxy, gc.DeepEquals, expectedProxy) 1168 } 1169 1170 func (s *withoutStateServerSuite) TestToolsRefusesWrongAgent(c *gc.C) { 1171 anAuthorizer := s.authorizer 1172 anAuthorizer.Tag = "machine-12354" 1173 anAuthorizer.EnvironManager = false 1174 anAuthorizer.MachineAgent = true 1175 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1176 c.Check(err, gc.IsNil) 1177 args := params.Entities{ 1178 Entities: []params.Entity{{Tag: s.machines[0].Tag()}}, 1179 } 1180 results, err := aProvisioner.Tools(args) 1181 // It is not an error to make the request, but the specific item is rejected 1182 c.Assert(err, gc.IsNil) 1183 c.Check(results.Results, gc.HasLen, 1) 1184 toolResult := results.Results[0] 1185 c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) 1186 } 1187 1188 func (s *withoutStateServerSuite) TestToolsForAgent(c *gc.C) { 1189 cur := version.Current 1190 agent := params.Entity{Tag: s.machines[0].Tag()} 1191 1192 // The machine must have its existing tools set before we query for the 1193 // next tools. This is so that we can grab Arch and Series without 1194 // having to pass it in again 1195 err := s.machines[0].SetAgentVersion(version.Current) 1196 c.Assert(err, gc.IsNil) 1197 1198 args := params.Entities{Entities: []params.Entity{agent}} 1199 results, err := s.provisioner.Tools(args) 1200 c.Assert(err, gc.IsNil) 1201 c.Check(results.Results, gc.HasLen, 1) 1202 c.Assert(results.Results[0].Error, gc.IsNil) 1203 agentTools := results.Results[0].Tools 1204 c.Check(agentTools.URL, gc.Not(gc.Equals), "") 1205 c.Check(agentTools.Version, gc.DeepEquals, cur) 1206 } 1207 1208 func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) { 1209 args := params.MachineContainersParams{ 1210 Params: []params.MachineContainers{ 1211 { 1212 MachineTag: "machine-0", 1213 ContainerTypes: []instance.ContainerType{instance.LXC}, 1214 }, 1215 { 1216 MachineTag: "machine-1", 1217 ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM}, 1218 }, 1219 }, 1220 } 1221 results, err := s.provisioner.SetSupportedContainers(args) 1222 c.Assert(err, gc.IsNil) 1223 c.Assert(results.Results, gc.HasLen, 2) 1224 for _, result := range results.Results { 1225 c.Assert(result.Error, gc.IsNil) 1226 } 1227 m0, err := s.State.Machine("0") 1228 c.Assert(err, gc.IsNil) 1229 containers, ok := m0.SupportedContainers() 1230 c.Assert(ok, jc.IsTrue) 1231 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC}) 1232 m1, err := s.State.Machine("1") 1233 c.Assert(err, gc.IsNil) 1234 containers, ok = m1.SupportedContainers() 1235 c.Assert(ok, jc.IsTrue) 1236 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 1237 } 1238 1239 func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) { 1240 // Login as a machine agent for machine 0. 1241 anAuthorizer := s.authorizer 1242 anAuthorizer.MachineAgent = true 1243 anAuthorizer.EnvironManager = false 1244 anAuthorizer.Tag = s.machines[0].Tag() 1245 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1246 c.Assert(err, gc.IsNil) 1247 c.Assert(aProvisioner, gc.NotNil) 1248 1249 args := params.MachineContainersParams{ 1250 Params: []params.MachineContainers{{ 1251 MachineTag: "machine-0", 1252 ContainerTypes: []instance.ContainerType{instance.LXC}, 1253 }, { 1254 MachineTag: "machine-1", 1255 ContainerTypes: []instance.ContainerType{instance.LXC}, 1256 }, { 1257 MachineTag: "machine-42", 1258 ContainerTypes: []instance.ContainerType{instance.LXC}, 1259 }, 1260 }, 1261 } 1262 // Only machine 0 can have it's containers updated. 1263 results, err := aProvisioner.SetSupportedContainers(args) 1264 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 1265 Results: []params.ErrorResult{ 1266 {Error: nil}, 1267 {Error: apiservertesting.ErrUnauthorized}, 1268 {Error: apiservertesting.ErrUnauthorized}, 1269 }, 1270 }) 1271 } 1272 1273 func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) { 1274 args := params.MachineContainersParams{ 1275 Params: []params.MachineContainers{ 1276 { 1277 MachineTag: "machine-0", 1278 }, 1279 }, 1280 } 1281 results, err := s.provisioner.SetSupportedContainers(args) 1282 c.Assert(err, gc.IsNil) 1283 c.Assert(results.Results, gc.HasLen, 1) 1284 c.Assert(results.Results[0].Error, gc.IsNil) 1285 m0, err := s.State.Machine("0") 1286 c.Assert(err, gc.IsNil) 1287 containers, ok := m0.SupportedContainers() 1288 c.Assert(ok, jc.IsTrue) 1289 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 1290 } 1291 1292 var _ = gc.Suite(&withStateServerSuite{}) 1293 1294 type withStateServerSuite struct { 1295 provisionerSuite 1296 } 1297 1298 func (s *withStateServerSuite) SetUpTest(c *gc.C) { 1299 s.provisionerSuite.setUpTest(c, true) 1300 } 1301 1302 func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) { 1303 hostPorts := [][]network.HostPort{{{ 1304 Address: network.NewAddress("0.1.2.3", network.ScopeUnknown), 1305 Port: 1234, 1306 }}} 1307 1308 err := s.State.SetAPIHostPorts(hostPorts) 1309 c.Assert(err, gc.IsNil) 1310 1311 result, err := s.provisioner.APIAddresses() 1312 c.Assert(err, gc.IsNil) 1313 c.Assert(result, gc.DeepEquals, params.StringsResult{ 1314 Result: []string{"0.1.2.3:1234"}, 1315 }) 1316 } 1317 1318 func (s *withStateServerSuite) TestStateAddresses(c *gc.C) { 1319 addresses, err := s.State.Addresses() 1320 c.Assert(err, gc.IsNil) 1321 1322 result, err := s.provisioner.StateAddresses() 1323 c.Assert(err, gc.IsNil) 1324 c.Assert(result, gc.DeepEquals, params.StringsResult{ 1325 Result: addresses, 1326 }) 1327 } 1328 1329 func (s *withStateServerSuite) TestCACert(c *gc.C) { 1330 result := s.provisioner.CACert() 1331 c.Assert(result, gc.DeepEquals, params.BytesResult{ 1332 Result: []byte(s.State.CACert()), 1333 }) 1334 } 1335 1336 func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) { 1337 s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait) 1338 c.Assert(s.resources.Count(), gc.Equals, 0) 1339 1340 _, err := s.provisioner.WatchMachineErrorRetry() 1341 c.Assert(err, gc.IsNil) 1342 1343 // Verify the resources were registered and stop them when done. 1344 c.Assert(s.resources.Count(), gc.Equals, 1) 1345 resource := s.resources.Get("1") 1346 defer statetesting.AssertStop(c, resource) 1347 1348 // Check that the Watch has consumed the initial event ("returned" 1349 // in the Watch call) 1350 wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) 1351 wc.AssertNoChange() 1352 1353 // We should now get a time triggered change. 1354 wc.AssertOneChange() 1355 1356 // Make sure WatchMachineErrorRetry fails with a machine agent login. 1357 anAuthorizer := s.authorizer 1358 anAuthorizer.MachineAgent = true 1359 anAuthorizer.EnvironManager = false 1360 aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) 1361 c.Assert(err, gc.IsNil) 1362 1363 result, err := aProvisioner.WatchMachineErrorRetry() 1364 c.Assert(err, gc.ErrorMatches, "permission denied") 1365 c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{}) 1366 }