160
159
func (s *BootstrapSuite) TestBootstrapAPIReadyRetries(c *gc.C) {
161
160
s.PatchValue(&bootstrapReadyPollDelay, 1*time.Millisecond)
162
161
s.PatchValue(&bootstrapReadyPollCount, 5)
163
defaultSeriesVersion := version.Current
162
defaultSeriesVersion := jujuversion.Current
164
163
// Force a dev version by having a non zero build number.
165
164
// This is because we have not uploaded any tools and auto
166
165
// upload is only enabled for dev versions.
167
166
defaultSeriesVersion.Build = 1234
168
s.PatchValue(&version.Current, defaultSeriesVersion)
167
s.PatchValue(&jujuversion.Current, defaultSeriesVersion)
169
168
for _, t := range []struct {
173
{0, ""}, // agent ready immediately
174
{2, ""}, // agent ready after 2 polls
175
{6, "upgrade in progress"}, // agent ready after 6 polls but that's too long
176
{-1, "other error"}, // another error is returned
172
{0, nil}, // agent ready immediately
173
{2, nil}, // agent ready after 2 polls
174
{6, &rpc.RequestError{
175
Message: params.CodeUpgradeInProgress,
176
Code: params.CodeUpgradeInProgress,
177
}}, // agent ready after 6 polls but that's too long
178
{-1, errOther}, // another error is returned
178
180
resetJujuXDGDataHome(c)
180
s.legacyMemStore = configstore.NewMem()
182
s.store = jujuclienttesting.NewMemStore()
182
184
s.mockBlockClient.numRetries = t.numRetries
183
185
s.mockBlockClient.retryCount = 0
308
307
c.Check(opBootstrap.Args.Placement, gc.Equals, test.placement)
310
309
opFinalizeBootstrap := (<-opc).(dummy.OpFinalizeBootstrap)
311
c.Check(opFinalizeBootstrap.Env, gc.Equals, "peckham-controller")
310
c.Check(opFinalizeBootstrap.Env, gc.Equals, "admin")
312
311
c.Check(opFinalizeBootstrap.InstanceConfig.Tools, gc.NotNil)
313
312
if test.upload != "" {
314
313
c.Check(opFinalizeBootstrap.InstanceConfig.Tools.Version.String(), gc.Equals, test.upload)
317
store, err := configstore.Default()
318
c.Assert(err, jc.ErrorIsNil)
320
// The controller should be recorded with the specified
321
// controller name, but the model should be called "admin".
323
// Check a CA cert/key was generated by reloading the controller.
324
316
expectedBootstrappedControllerName := bootstrappedControllerName(controllerName)
325
info, err := store.ReadInfo(expectedBootstrappedControllerName + ":" + controllerName)
326
c.Assert(err, jc.ErrorIsNil)
327
c.Assert(info, gc.NotNil)
328
cfg, err := config.New(config.NoDefaults, info.BootstrapConfig())
329
c.Assert(err, jc.ErrorIsNil)
330
c.Assert(cfg.Name(), gc.Equals, "peckham-controller")
331
_, hasCert := cfg.CACert()
332
c.Check(hasCert, jc.IsTrue)
333
_, hasKey := cfg.CAPrivateKey()
334
c.Check(hasKey, jc.IsTrue)
335
c.Assert(info.APIEndpoint().Addresses, gc.DeepEquals, []string{addrConnectedTo})
337
// Check controllers.yaml has controller
338
endpoint := info.APIEndpoint()
339
controllerStore := jujuclient.NewFileClientStore()
340
controller, err := controllerStore.ControllerByName(expectedBootstrappedControllerName)
341
c.Assert(err, jc.ErrorIsNil)
342
c.Assert(controller.CACert, gc.Equals, endpoint.CACert)
343
c.Assert(controller.Servers, gc.DeepEquals, endpoint.Hostnames)
344
c.Assert(controller.APIEndpoints, gc.DeepEquals, endpoint.Addresses)
345
c.Assert(controller.ControllerUUID, gc.Equals, endpoint.ServerUUID)
318
// Check controllers.yaml controller details.
319
addrConnectedTo := []string{"localhost:17070"}
321
controller, err := s.store.ControllerByName(expectedBootstrappedControllerName)
322
c.Assert(err, jc.ErrorIsNil)
323
c.Assert(controller.CACert, gc.Not(gc.Equals), "")
324
c.Assert(controller.UnresolvedAPIEndpoints, gc.DeepEquals, addrConnectedTo)
325
c.Assert(controller.APIEndpoints, gc.DeepEquals, addrConnectedTo)
326
c.Assert(utils.IsValidUUIDString(controller.ControllerUUID), jc.IsTrue)
328
// Controller model should be called "admin".
329
controllerModel, err := s.store.ModelByName(expectedBootstrappedControllerName, "admin@local", "admin")
330
c.Assert(controllerModel.ModelUUID, gc.Equals, controller.ControllerUUID)
331
c.Assert(err, jc.ErrorIsNil)
333
// Bootstrap config should have been saved, and should only contain
334
// the type, name, and any user-supplied configuration.
335
bootstrapConfig, err := s.store.BootstrapConfigForController(expectedBootstrappedControllerName)
336
c.Assert(err, jc.ErrorIsNil)
337
c.Assert(bootstrapConfig.Cloud, gc.Equals, "dummy")
338
c.Assert(bootstrapConfig.Credential, gc.Equals, "")
339
c.Assert(bootstrapConfig.Config, jc.DeepEquals, map[string]interface{}{
342
"default-series": "raring",
480
479
currentController, err := modelcmd.ReadCurrentController()
481
480
c.Assert(err, jc.ErrorIsNil)
482
481
c.Assert(currentController, gc.Equals, bootstrappedControllerName("devcontroller"))
482
modelName, err := s.store.CurrentModel(currentController, "admin@local")
483
c.Assert(err, jc.ErrorIsNil)
484
c.Assert(modelName, gc.Equals, "default")
487
func (s *BootstrapSuite) TestBootstrapDefaultModel(c *gc.C) {
488
s.patchVersionAndSeries(c, "raring")
490
var bootstrap fakeBootstrapFuncs
491
s.PatchValue(&getBootstrapFuncs, func() BootstrapInterface {
495
coretesting.RunCommand(
496
c, s.newBootstrapCommand(),
497
"devcontroller", "dummy",
499
"--default-model", "mymodel",
500
"--config", "foo=bar",
502
c.Assert(bootstrap.args.HostedModelConfig["name"], gc.Equals, "mymodel")
503
c.Assert(bootstrap.args.HostedModelConfig["foo"], gc.Equals, "bar")
506
func (s *BootstrapSuite) TestBootstrapDefaultConfigStripsProcessedAttributes(c *gc.C) {
507
s.patchVersionAndSeries(c, "raring")
509
var bootstrap fakeBootstrapFuncs
510
s.PatchValue(&getBootstrapFuncs, func() BootstrapInterface {
514
fakeSSHFile := filepath.Join(c.MkDir(), "ssh")
515
err := ioutil.WriteFile(fakeSSHFile, []byte("ssh-key"), 0600)
516
c.Assert(err, jc.ErrorIsNil)
517
coretesting.RunCommand(
518
c, s.newBootstrapCommand(),
519
"devcontroller", "dummy",
521
"--config", "authorized-keys-path="+fakeSSHFile,
523
_, ok := bootstrap.args.HostedModelConfig["authorized-keys-path"]
524
c.Assert(ok, jc.IsFalse)
527
func (s *BootstrapSuite) TestBootstrapDefaultConfigStripsInheritedAttributes(c *gc.C) {
528
s.patchVersionAndSeries(c, "raring")
530
var bootstrap fakeBootstrapFuncs
531
s.PatchValue(&getBootstrapFuncs, func() BootstrapInterface {
535
fakeSSHFile := filepath.Join(c.MkDir(), "ssh")
536
err := ioutil.WriteFile(fakeSSHFile, []byte("ssh-key"), 0600)
537
c.Assert(err, jc.ErrorIsNil)
538
coretesting.RunCommand(
539
c, s.newBootstrapCommand(),
540
"devcontroller", "dummy",
542
"--config", "authorized-keys=ssh-key",
543
"--config", "agent-version=1.19.0",
545
_, ok := bootstrap.args.HostedModelConfig["authorized-keys"]
546
c.Assert(ok, jc.IsFalse)
547
_, ok = bootstrap.args.HostedModelConfig["agent-version"]
548
c.Assert(ok, jc.IsFalse)
485
551
type mockBootstrapInstance struct {
534
598
c.Check(destroyed, jc.IsFalse)
601
func (s *BootstrapSuite) writeControllerModelAccountInfo(c *gc.C, controller, model, account string) {
602
err := s.store.UpdateController(controller, jujuclient.ControllerDetails{
606
c.Assert(err, jc.ErrorIsNil)
607
err = modelcmd.WriteCurrentController(controller)
608
c.Assert(err, jc.ErrorIsNil)
609
err = s.store.UpdateAccount(controller, account, jujuclient.AccountDetails{
613
c.Assert(err, jc.ErrorIsNil)
614
err = s.store.SetCurrentAccount(controller, account)
615
c.Assert(err, jc.ErrorIsNil)
616
err = s.store.UpdateModel(controller, account, model, jujuclient.ModelDetails{
617
ModelUUID: "model-uuid",
619
c.Assert(err, jc.ErrorIsNil)
620
err = s.store.SetCurrentModel(controller, account, model)
621
c.Assert(err, jc.ErrorIsNil)
624
func (s *BootstrapSuite) TestBootstrapErrorRestoresOldMetadata(c *gc.C) {
625
s.patchVersionAndSeries(c, "raring")
626
s.PatchValue(&environsPrepare, func(
627
environs.BootstrapContext,
628
jujuclient.ClientStore,
629
environs.PrepareParams,
630
) (environs.Environ, error) {
631
s.writeControllerModelAccountInfo(c, "foo", "bar", "foobar@local")
632
return nil, fmt.Errorf("mock-prepare")
635
s.writeControllerModelAccountInfo(c, "local.olddevcontroller", "fredmodel", "fred@local")
636
_, err := coretesting.RunCommand(c, s.newBootstrapCommand(), "devcontroller", "dummy", "--auto-upgrade")
637
c.Assert(err, gc.ErrorMatches, "mock-prepare")
639
oldCurrentController, err := modelcmd.ReadCurrentController()
640
c.Assert(err, jc.ErrorIsNil)
641
c.Assert(oldCurrentController, gc.Equals, bootstrappedControllerName("olddevcontroller"))
642
oldCurrentAccount, err := s.store.CurrentAccount(oldCurrentController)
643
c.Assert(err, jc.ErrorIsNil)
644
c.Assert(oldCurrentAccount, gc.Equals, "fred@local")
645
oldCurrentModel, err := s.store.CurrentModel(oldCurrentController, oldCurrentAccount)
646
c.Assert(err, jc.ErrorIsNil)
647
c.Assert(oldCurrentModel, gc.Equals, "fredmodel")
537
650
func (s *BootstrapSuite) TestBootstrapAlreadyExists(c *gc.C) {
538
651
const controllerName = "devcontroller"
539
652
expectedBootstrappedName := bootstrappedControllerName(controllerName)
540
653
s.patchVersionAndSeries(c, "raring")
542
store := jujuclient.NewFileClientStore()
543
err := store.UpdateController("local.devcontroller", jujuclient.ControllerDetails{
547
c.Assert(err, jc.ErrorIsNil)
655
s.writeControllerModelAccountInfo(c, "local.devcontroller", "fredmodel", "fred@local")
549
657
ctx := coretesting.Context(c)
550
658
_, errc := cmdtesting.RunCommand(ctx, s.newBootstrapCommand(), controllerName, "dummy", "--auto-upgrade")
552
660
c.Assert(err, jc.Satisfies, errors.IsAlreadyExists)
553
661
c.Assert(err, gc.ErrorMatches, fmt.Sprintf(`controller %q already exists`, expectedBootstrappedName))
662
currentController, err := modelcmd.ReadCurrentController()
663
c.Assert(err, jc.ErrorIsNil)
664
c.Assert(currentController, gc.Equals, "local.devcontroller")
665
currentAccount, err := s.store.CurrentAccount(currentController)
666
c.Assert(err, jc.ErrorIsNil)
667
c.Assert(currentAccount, gc.Equals, "fred@local")
668
currentModel, err := s.store.CurrentModel(currentController, currentAccount)
669
c.Assert(err, jc.ErrorIsNil)
670
c.Assert(currentModel, gc.Equals, "fredmodel")
556
673
func (s *BootstrapSuite) TestInvalidLocalSource(c *gc.C) {
557
s.PatchValue(&version.Current, version.MustParse("1.2.0"))
674
s.PatchValue(&jujuversion.Current, version.MustParse("1.2.0"))
558
675
resetJujuXDGDataHome(c)
560
677
// Bootstrap the controller with an invalid source.
668
785
c.Assert(err, jc.ErrorIsNil)
670
store, err := configstore.Default()
671
c.Assert(err, jc.ErrorIsNil)
673
info, err := store.ReadInfo(bootstrappedControllerName("devcontroller") + ":devcontroller")
674
c.Assert(err, jc.ErrorIsNil)
675
cfg, err := config.New(config.NoDefaults, info.BootstrapConfig())
676
c.Assert(err, jc.ErrorIsNil)
677
env, err := environs.New(cfg)
787
p, err := environs.Provider("dummy")
788
c.Assert(err, jc.ErrorIsNil)
789
cfg, err := modelcmd.NewGetBootstrapConfigFunc(s.store)("devcontroller")
790
c.Assert(err, jc.ErrorIsNil)
791
env, err := p.PrepareForBootstrap(envtesting.BootstrapContext(c), cfg)
678
792
c.Assert(err, jc.ErrorIsNil)
680
794
// Now check the available tools which are the 1.2.0 envtools.