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