// Bootstrap is specified in the Environ interface. func (env *azureEnviron) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, err error) { // The creation of the affinity group and the virtual network is specific to the Azure provider. err = env.createAffinityGroup() if err != nil && !isHTTPConflict(err) { return "", "", nil, err } // If we fail after this point, clean up the affinity group. defer func() { if err != nil { env.deleteAffinityGroup() } }() err = env.createVirtualNetwork() if err != nil && !isVirtualNetworkExist(err) { return "", "", nil, err } // If we fail after this point, clean up the virtual network. defer func() { if err != nil { env.deleteVirtualNetwork() } }() return common.Bootstrap(ctx, env, args) }
func (s *BootstrapSuite) TestCannotRecordStartedInstance(c *gc.C) { innerStorage := newStorage(s, c) stor := &mockStorage{Storage: innerStorage} startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, _ *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { stor.putErr = fmt.Errorf("suddenly a wild blah") return &mockInstance{id: "i-blah"}, nil, nil, nil } var stopped []instance.Id stopInstances := func(ids []instance.Id) error { stopped = append(stopped, ids...) return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, stopInstances: stopInstances, config: configGetter(c), } ctx := coretesting.Context(c) err := common.Bootstrap(ctx, env, environs.BootstrapParams{}) c.Assert(err, gc.ErrorMatches, "cannot save state: suddenly a wild blah") c.Assert(stopped, gc.HasLen, 1) c.Assert(stopped[0], gc.Equals, instance.Id("i-blah")) }
func (s *BootstrapSuite) TestCannotStartInstance(c *gc.C) { checkPlacement := "directive" checkCons := constraints.MustParse("mem=8G") startInstance := func( placement string, cons constraints.Value, _ []string, possibleTools tools.List, mcfg *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { c.Assert(placement, gc.DeepEquals, checkPlacement) c.Assert(cons, gc.DeepEquals, checkCons) c.Assert(mcfg, gc.DeepEquals, environs.NewBootstrapMachineConfig(mcfg.SystemPrivateSSHKey)) return nil, nil, nil, fmt.Errorf("meh, not started") } env := &mockEnviron{ storage: newStorage(s, c), startInstance: startInstance, config: configGetter(c), } ctx := coretesting.Context(c) err := common.Bootstrap(ctx, env, environs.BootstrapParams{ Constraints: checkCons, Placement: checkPlacement, }) c.Assert(err, gc.ErrorMatches, "cannot start bootstrap instance: meh, not started") }
func (s *BootstrapSuite) TestKeepBrokenDoesNoStop(c *gc.C) { innerStorage := newStorage(s, c) stor := &mockStorage{Storage: innerStorage} checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, mcfg *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { stor.putErr = fmt.Errorf("suddenly a wild blah") return &mockInstance{id: "i-blah"}, &checkHardware, nil, nil } stopInstances := func(instances []instance.Id) error { c.Errorf("unexpected call to StopInstances") return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, stopInstances: stopInstances, config: configGetter(c), } ctx := coretesting.Context(c) _, _, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ KeepBroken: true, AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, gc.ErrorMatches, "cannot save state: suddenly a wild blah") }
func (e *Environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (*environs.BootstrapResult, error) { // The client's authentication may have been reset when finding tools if the agent-version // attribute was updated so we need to re-authenticate. This will be a no-op if already authenticated. // An authenticated client is needed for the URL() call below. if err := authenticateClient(e); err != nil { return nil, err } return common.Bootstrap(ctx, e, args) }
func (s *BootstrapSuite) TestCannotStartInstance(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) checkPlacement := "directive" checkCons := constraints.MustParse("mem=8G") env := &mockEnviron{ storage: newStorage(s, c), config: configGetter(c), } startInstance := func( placement string, cons constraints.Value, _ []string, possibleTools tools.List, icfg *instancecfg.InstanceConfig, ) (instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error) { c.Assert(placement, gc.DeepEquals, checkPlacement) c.Assert(cons, gc.DeepEquals, checkCons) // The machine config should set its upgrade behavior based on // the environment config. expectedMcfg, err := instancecfg.NewBootstrapInstanceConfig(coretesting.FakeControllerConfig(), cons, cons, icfg.Series, "") c.Assert(err, jc.ErrorIsNil) expectedMcfg.EnableOSRefreshUpdate = env.Config().EnableOSRefreshUpdate() expectedMcfg.EnableOSUpgrade = env.Config().EnableOSUpgrade() expectedMcfg.Tags = map[string]string{ "juju-model-uuid": coretesting.ModelTag.Id(), "juju-controller-uuid": coretesting.ControllerTag.Id(), "juju-is-controller": "true", } c.Assert(icfg, jc.DeepEquals, expectedMcfg) return nil, nil, nil, errors.Errorf("meh, not started") } env.startInstance = startInstance ctx := envtesting.BootstrapContext(c) _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), BootstrapConstraints: checkCons, ModelConstraints: checkCons, Placement: checkPlacement, AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), }, }, }}) c.Assert(err, gc.ErrorMatches, "cannot start bootstrap instance: meh, not started") }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } inner := coretesting.Context(c) ctx := modelcmd.BootstrapContext(inner) result, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), }, }, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(result.Series, gc.Equals, config.PreferredSeries(mocksConfig)) output := inner.Stderr.(*bytes.Buffer) lines := strings.Split(output.String(), "\n") c.Assert(len(lines), jc.GreaterThan, 1) c.Assert(lines[0], gc.Equals, "Some message") }
func (s *BootstrapSuite) TestBootstrapSeries(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) s.PatchValue(&series.HostSeries, func() string { return "precise" }) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func(_ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig) (instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var numGetConfigCalled int getConfig := func() *config.Config { numGetConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } ctx := envtesting.BootstrapContext(c) bootstrapSeries := "utopic" result, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), BootstrapSeries: bootstrapSeries, AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: bootstrapSeries, }, }, }}) c.Assert(err, jc.ErrorIsNil) c.Check(result.Arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Check(result.Series, gc.Equals, bootstrapSeries) }
// Bootstrap is part of the Environ interface. func (env *azureEnviron) Bootstrap( ctx environs.BootstrapContext, args environs.BootstrapParams, ) (*environs.BootstrapResult, error) { if err := env.initResourceGroup(args.ControllerConfig.ControllerUUID()); err != nil { return nil, errors.Annotate(err, "creating controller resource group") } result, err := common.Bootstrap(ctx, env, args) if err != nil { logger.Errorf("bootstrap failed, destroying model: %v", err) if err := env.Destroy(); err != nil { logger.Errorf("failed to destroy model: %v", err) } return nil, errors.Trace(err) } return result, nil }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, mcfg *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } restore := envtesting.DisableFinishBootstrap() defer restore() env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } originalAuthKeys := env.Config().AuthorizedKeys() ctx := coretesting.Context(c) err := common.Bootstrap(ctx, env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) authKeys := env.Config().AuthorizedKeys() c.Assert(authKeys, gc.Not(gc.Equals), originalAuthKeys) c.Assert(authKeys, jc.HasSuffix, "juju-system-key\n") }
func (s *BootstrapSuite) TestCannotRecordThenCannotStop(c *gc.C) { innerStorage := newStorage(s, c) stor := &mockStorage{Storage: innerStorage} startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, _ *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { stor.putErr = fmt.Errorf("suddenly a wild blah") return &mockInstance{id: "i-blah"}, nil, nil, nil } var stopped []instance.Id stopInstances := func(instances []instance.Id) error { stopped = append(stopped, instances...) return fmt.Errorf("bork bork borken") } var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("bootstrap-tester", &tw, loggo.DEBUG), gc.IsNil) defer loggo.RemoveWriter("bootstrap-tester") env := &mockEnviron{ storage: stor, startInstance: startInstance, stopInstances: stopInstances, config: configGetter(c), } ctx := coretesting.Context(c) _, _, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, gc.ErrorMatches, "cannot save state: suddenly a wild blah") c.Assert(stopped, gc.HasLen, 1) c.Assert(stopped[0], gc.Equals, instance.Id("i-blah")) c.Assert(tw.Log(), jc.LogMatches, []jc.SimpleMessage{{ loggo.ERROR, `cannot stop failed bootstrap instance "i-blah": bork bork borken`, }}) }
func (s *BootstrapSuite) TestCannotStartInstance(c *gc.C) { checkPlacement := "directive" checkCons := constraints.MustParse("mem=8G") env := &mockEnviron{ storage: newStorage(s, c), config: configGetter(c), } startInstance := func( placement string, cons constraints.Value, _ []string, possibleTools tools.List, mcfg *cloudinit.MachineConfig, ) (instance.Instance, *instance.HardwareCharacteristics, []network.Info, error) { c.Assert(placement, gc.DeepEquals, checkPlacement) c.Assert(cons, gc.DeepEquals, checkCons) // The machine config should set its upgrade behavior based on // the environment config. expectedMcfg, err := environs.NewBootstrapMachineConfig(cons, mcfg.Series) c.Assert(err, gc.IsNil) expectedMcfg.EnableOSRefreshUpdate = env.Config().EnableOSRefreshUpdate() expectedMcfg.EnableOSUpgrade = env.Config().EnableOSUpgrade() c.Assert(mcfg, gc.DeepEquals, expectedMcfg) return nil, nil, nil, fmt.Errorf("meh, not started") } env.startInstance = startInstance ctx := coretesting.Context(c) _, _, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ Constraints: checkCons, Placement: checkPlacement, AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, gc.ErrorMatches, "cannot start bootstrap instance: meh, not started") }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { s.PatchValue(&version.Current.Number, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } ctx := envtesting.BootstrapContext(c) arch, series, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, jc.ErrorIsNil) c.Assert(arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(series, gc.Equals, config.PreferredSeries(mocksConfig)) }
// Bootstrap is specified in the Environ interface. func (env *azureEnviron) Bootstrap( ctx environs.BootstrapContext, args environs.BootstrapParams, ) (*environs.BootstrapResult, error) { cfg, err := env.initResourceGroup() if err != nil { return nil, errors.Annotate(err, "creating controller resource group") } if err := env.SetConfig(cfg); err != nil { return nil, errors.Annotate(err, "updating config") } result, err := common.Bootstrap(ctx, env, args) if err != nil { logger.Errorf("bootstrap failed, destroying environment: %v", err) if err := env.Destroy(); err != nil { logger.Errorf("failed to destroy environment: %v", err) } return nil, errors.Trace(err) } return result, nil }
// Bootstrap initializes the state for the environment, possibly // starting one or more instances. If the configuration's // AdminSecret is non-empty, the administrator password on the // newly bootstrapped state will be set to a hash of it (see // utils.PasswordHash), When first connecting to the // environment via the juju package, the password hash will be // automatically replaced by the real password. // // The supplied constraints are used to choose the initial instance // specification, and will be stored in the new environment's state. // // Bootstrap is responsible for selecting the appropriate tools, // and setting the agent-version configuration attribute prior to // bootstrapping the environment. func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (*environs.BootstrapResult, error) { return common.Bootstrap(ctx, env, params) }
func (env *joyentEnviron) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) { return common.Bootstrap(ctx, env, args) }
func (env *joyentEnviron) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (*environs.BootstrapResult, error) { return common.Bootstrap(ctx, env, args) }
// Bootstrap initializes the state for the environment, possibly // starting one or more instances. If the configuration's // AdminSecret is non-empty, the administrator password on the // newly bootstrapped state will be set to a hash of it (see // utils.PasswordHash), When first connecting to the // environment via the juju package, the password hash will be // automatically replaced by the real password. // // The supplied constraints are used to choose the initial instance // specification, and will be stored in the new environment's state. // // Bootstrap is responsible for selecting the appropriate tools, // and setting the agent-version configuration attribute prior to // bootstrapping the environment. func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (string, string, environs.BootstrapFinalizer, error) { return common.Bootstrap(ctx, env, params) }