func (t *Tests) TestBootstrap(c *gc.C) { e := t.Prepare(c) err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), e, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) controllerInstances, err := e.ControllerInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(controllerInstances, gc.Not(gc.HasLen), 0) e2 := t.Open(c, e.Config()) controllerInstances2, err := e2.ControllerInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0) c.Assert(controllerInstances2, jc.SameContents, controllerInstances) err = environs.Destroy(e2.Config().Name(), e2, t.ControllerStore) c.Assert(err, jc.ErrorIsNil) // Prepare again because Destroy invalidates old environments. e3 := t.Prepare(c) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), e3, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) err = environs.Destroy(e3.Config().Name(), e3, t.ControllerStore) c.Assert(err, jc.ErrorIsNil) }
// Run implements Command.Run func (c *killCommand) Run(ctx *cmd.Context) error { controllerName := c.ControllerName() store := c.ClientStore() if !c.assumeYes { if err := confirmDestruction(ctx, controllerName); err != nil { return err } } // Attempt to connect to the API. api, err := c.getControllerAPI() switch { case err == nil: defer api.Close() case errors.Cause(err) == common.ErrPerm: return errors.Annotate(err, "cannot destroy controller") default: if errors.Cause(err) != modelcmd.ErrConnTimedOut { logger.Debugf("unable to open api: %s", err) } ctx.Infof("Unable to open API: %s\n", err) api = nil } // Obtain controller environ so we can clean up afterwards. controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api) if err != nil { return errors.Annotate(err, "getting controller environ") } // If we were unable to connect to the API, just destroy the controller through // the environs interface. if api == nil { ctx.Infof("Unable to connect to the API server. Destroying through provider.") return environs.Destroy(controllerName, controllerEnviron, store) } // Attempt to destroy the controller and all environments. err = api.DestroyController(true) if err != nil { ctx.Infof("Unable to destroy controller through the API: %s. Destroying through provider.", err) return environs.Destroy(controllerName, controllerEnviron, store) } ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", controllerName) updateStatus := newTimedStatusUpdater(ctx, api, controllerEnviron.Config().UUID()) for ctrStatus, envsStatus := updateStatus(0); hasUnDeadModels(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) { ctx.Infof(fmtCtrStatus(ctrStatus)) for _, envStatus := range envsStatus { ctx.Verbosef(fmtModelStatus(envStatus)) } } ctx.Infof("All hosted models reclaimed, cleaning up controller machines") return environs.Destroy(controllerName, controllerEnviron, store) }
func (t *Tests) TestBootstrap(c *gc.C) { credential := t.Credential if credential.AuthType() == "" { credential = cloud.NewEmptyCredential() } var regions []cloud.Region if t.CloudRegion != "" { regions = []cloud.Region{{ Name: t.CloudRegion, Endpoint: t.CloudEndpoint, }} } args := bootstrap.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), CloudName: t.TestConfig["type"].(string), Cloud: cloud.Cloud{ Type: t.TestConfig["type"].(string), AuthTypes: []cloud.AuthType{credential.AuthType()}, Regions: regions, Endpoint: t.CloudEndpoint, }, CloudRegion: t.CloudRegion, CloudCredential: &credential, CloudCredentialName: "credential", AdminSecret: AdminSecret, CAPrivateKey: coretesting.CAKey, } e := t.Prepare(c) err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), e, args) c.Assert(err, jc.ErrorIsNil) controllerInstances, err := e.ControllerInstances(t.ControllerUUID) c.Assert(err, jc.ErrorIsNil) c.Assert(controllerInstances, gc.Not(gc.HasLen), 0) e2 := t.Open(c, e.Config()) controllerInstances2, err := e2.ControllerInstances(t.ControllerUUID) c.Assert(err, jc.ErrorIsNil) c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0) c.Assert(controllerInstances2, jc.SameContents, controllerInstances) err = environs.Destroy(e2.Config().Name(), e2, t.ControllerStore) c.Assert(err, jc.ErrorIsNil) // Prepare again because Destroy invalidates old environments. e3 := t.Prepare(c) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), e3, args) c.Assert(err, jc.ErrorIsNil) err = environs.Destroy(e3.Config().Name(), e3, t.ControllerStore) c.Assert(err, jc.ErrorIsNil) }
// Run implements Command.Run func (c *killCommand) Run(ctx *cmd.Context) error { controllerName := c.ControllerName() store := c.ClientStore() if !c.assumeYes { if err := confirmDestruction(ctx, controllerName); err != nil { return err } } // Attempt to connect to the API. api, err := c.getControllerAPI() switch { case err == nil: defer api.Close() case errors.Cause(err) == common.ErrPerm: return errors.Annotate(err, "cannot destroy controller") default: if errors.Cause(err) != modelcmd.ErrConnTimedOut { logger.Debugf("unable to open api: %s", err) } ctx.Infof("Unable to open API: %s\n", err) api = nil } // Obtain controller environ so we can clean up afterwards. controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api) if err != nil { return errors.Annotate(err, "getting controller environ") } // If we were unable to connect to the API, just destroy the controller through // the environs interface. if api == nil { ctx.Infof("Unable to connect to the API server, destroying through provider") return environs.Destroy(controllerName, controllerEnviron, store) } // Attempt to destroy the controller and all environments. err = api.DestroyController(true) if err != nil { ctx.Infof("Unable to destroy controller through the API: %s\nDestroying through provider", err) return environs.Destroy(controllerName, controllerEnviron, store) } ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", controllerName) uuid := controllerEnviron.Config().UUID() if err := c.WaitForModels(ctx, api, uuid); err != nil { c.DirectDestroyRemaining(ctx, api) } return environs.Destroy(controllerName, controllerEnviron, store) }
func (*OpenSuite) TestDestroy(c *gc.C) { cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge( testing.Attrs{ "name": "erewhemos", }, )) c.Assert(err, jc.ErrorIsNil) store := jujuclienttesting.NewMemStore() // Prepare the environment and sanity-check that // the config storage info has been made. controllerCfg := testing.FakeControllerConfig() ctx := envtesting.BootstrapContext(c) e, err := bootstrap.Prepare(ctx, store, bootstrap.PrepareParams{ ControllerConfig: controllerCfg, ControllerName: "controller-name", ModelConfig: cfg.AllAttrs(), Cloud: dummy.SampleCloudSpec(), AdminSecret: "admin-secret", }) c.Assert(err, jc.ErrorIsNil) _, err = store.ControllerByName("controller-name") c.Assert(err, jc.ErrorIsNil) err = environs.Destroy("controller-name", e, store) c.Assert(err, jc.ErrorIsNil) // Check that the environment has actually been destroyed // and that the controller details been removed too. _, err = e.ControllerInstances(controllerCfg.ControllerUUID()) c.Assert(err, gc.ErrorMatches, "model is not prepared") _, err = store.ControllerByName("controller-name") c.Assert(err, jc.Satisfies, errors.IsNotFound) }
func (c *DestroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) { store, err := configstore.Default() if err != nil { return fmt.Errorf("cannot open environment info storage: %v", err) } environ, err := environs.NewFromName(c.envName, store) if err != nil { if environs.IsEmptyConfig(err) { // Delete the .jenv file and call it done. ctx.Infof("removing empty environment file") return environs.DestroyInfo(c.envName, store) } return err } if !c.assumeYes { fmt.Fprintf(ctx.Stdout, destroyEnvMsg, environ.Name(), environ.Config().Type()) scanner := bufio.NewScanner(ctx.Stdin) scanner.Scan() err := scanner.Err() if err != nil && err != io.EOF { return fmt.Errorf("Environment destruction aborted: %s", err) } answer := strings.ToLower(scanner.Text()) if answer != "y" && answer != "yes" { return errors.New("environment destruction aborted") } } // If --force is supplied, then don't attempt to use the API. // This is necessary to destroy broken environments, where the // API server is inaccessible or faulty. if !c.force { defer func() { if result == nil { return } logger.Errorf(`failed to destroy environment %q If the environment is unusable, then you may run juju destroy-environment --force to forcefully destroy the environment. Upon doing so, review your environment provider console for any resources that need to be cleaned up. `, c.envName) }() apiclient, err := juju.NewAPIClientFromName(c.envName) if err != nil { return fmt.Errorf("cannot connect to API: %v", err) } defer apiclient.Close() err = apiclient.DestroyEnvironment() if err != nil && !params.IsCodeNotImplemented(err) { return fmt.Errorf("destroying environment: %v", err) } } return environs.Destroy(environ, store) }
func (*OpenSuite) TestDestroy(c *gc.C) { cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge( testing.Attrs{ "state-server": false, "name": "erewhemos", }, )) c.Assert(err, gc.IsNil) store := configstore.NewMem() // Prepare the environment and sanity-check that // the config storage info has been made. ctx := testing.Context(c) e, err := environs.Prepare(cfg, ctx, store) c.Assert(err, gc.IsNil) _, err = store.ReadInfo(e.Config().Name()) c.Assert(err, gc.IsNil) err = environs.Destroy(e, store) c.Assert(err, gc.IsNil) // Check that the environment has actually been destroyed // and that the config info has been destroyed too. _, err = e.StateServerInstances() c.Assert(err, gc.ErrorMatches, "environment has been destroyed") _, err = store.ReadInfo(e.Config().Name()) c.Assert(err, jc.Satisfies, errors.IsNotFound) }
// Run implements Command.Run func (c *destroyCommand) Run(ctx *cmd.Context) error { store, err := configstore.Default() if err != nil { return errors.Annotate(err, "cannot open controller info storage") } cfgInfo, err := store.ReadInfo(c.ModelName()) if err != nil { return errors.Annotate(err, "cannot read controller info") } // Verify that we're destroying a controller apiEndpoint := cfgInfo.APIEndpoint() if apiEndpoint.ServerUUID != "" && apiEndpoint.ModelUUID != apiEndpoint.ServerUUID { return errors.Errorf("%q is not a controller; use juju model destroy to destroy it", c.ModelName()) } if !c.assumeYes { if err = confirmDestruction(ctx, c.ModelName()); err != nil { return err } } // Attempt to connect to the API. If we can't, fail the destroy. Users will // need to use the controller kill command if we can't connect. api, err := c.getControllerAPI() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil) } defer api.Close() // Obtain bootstrap / controller environ information controllerEnviron, err := c.getControllerEnviron(cfgInfo, api) if err != nil { return errors.Annotate(err, "cannot obtain bootstrap information") } // Attempt to destroy the controller. err = api.DestroyController(c.destroyEnvs) if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, api) } ctx.Infof("Destroying controller %q", c.ModelName()) if c.destroyEnvs { ctx.Infof("Waiting for hosted model resources to be reclaimed.") updateStatus := newTimedStatusUpdater(ctx, api, apiEndpoint.ModelUUID) for ctrStatus, envsStatus := updateStatus(0); hasUnDeadEnvirons(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) { ctx.Infof(fmtCtrStatus(ctrStatus)) for _, envStatus := range envsStatus { ctx.Verbosef(fmtEnvStatus(envStatus)) } } ctx.Infof("All hosted models reclaimed, cleaning up controller machines") } return environs.Destroy(controllerEnviron, store) }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) { if !t.HasProvisioner { c.Skip("HasProvisioner is false; cannot test deployment") } current := version.Current other := current other.Series = "quantal" if current == other { other.Series = "precise" } dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{ "state-server": false, "name": "dummy storage", })) dummyenv, err := environs.Prepare(dummyCfg, coretesting.Context(c), configstore.NewMem()) c.Assert(err, gc.IsNil) defer dummyenv.Destroy() t.Destroy(c) attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series}) cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, gc.IsNil) env, err := environs.Prepare(cfg, coretesting.Context(c), t.ConfigStore) c.Assert(err, gc.IsNil) defer environs.Destroy(env, t.ConfigStore) currentName := envtools.StorageName(current) otherName := envtools.StorageName(other) envStorage := env.Storage() dummyStorage := dummyenv.Storage() defer envStorage.Remove(otherName) _, err = sync.Upload(dummyStorage, ¤t.Number) c.Assert(err, gc.IsNil) // This will only work while cross-compiling across releases is safe, // which depends on external elements. Tends to be safe for the last // few releases, but we may have to refactor some day. err = storageCopy(dummyStorage, currentName, envStorage, otherName) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) st := t.Env.(testing.GetStater).GetStateInAPIServer() // Wait for machine agent to come up on the bootstrap // machine and ensure it deployed the proper series. m0, err := st.Machine("0") c.Assert(err, gc.IsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
// destroyPreparedEnviron destroys the environment and logs an error if it fails. func destroyPreparedEnviron(ctx *cmd.Context, env environs.Environ, store configstore.Storage, err *error, action string) { if *err == nil { return } ctx.Infof("%s failed, destroying environment", action) if err := environs.Destroy(env, store); err != nil { logger.Errorf("%s failed, and the environment could not be destroyed: %v", action, err) } }
func (t *Tests) TestBootstrap(c *gc.C) { e := t.Prepare(c) t.UploadFakeTools(c, e.Storage()) err := bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e, bootstrap.BootstrapParams{}) c.Assert(err, gc.IsNil) stateServerInstances, err := e.StateServerInstances() c.Assert(err, gc.IsNil) c.Assert(stateServerInstances, gc.Not(gc.HasLen), 0) err = bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") e2 := t.Open(c) t.UploadFakeTools(c, e2.Storage()) err = bootstrap.EnsureNotBootstrapped(e2) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") stateServerInstances2, err := e2.StateServerInstances() c.Assert(err, gc.IsNil) c.Assert(stateServerInstances2, gc.Not(gc.HasLen), 0) c.Assert(stateServerInstances2, jc.SameContents, stateServerInstances) err = environs.Destroy(e2, t.ConfigStore) c.Assert(err, gc.IsNil) // Prepare again because Destroy invalidates old environments. e3 := t.Prepare(c) t.UploadFakeTools(c, e3.Storage()) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e3, bootstrap.BootstrapParams{}) c.Assert(err, gc.IsNil) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") err = environs.Destroy(e3, t.ConfigStore) c.Assert(err, gc.IsNil) }
func (t *LiveTests) Destroy(c *gc.C) { if t.Env == nil { return } err := environs.Destroy(t.Env, t.ConfigStore) c.Assert(err, gc.IsNil) t.bootstrapped = false t.prepared = false t.Env = nil }
func (t *LiveTests) Destroy(c *gc.C) { if t.Env == nil { return } err := environs.Destroy(t.Env.Config().Name(), t.Env, t.ControllerStore) c.Assert(err, jc.ErrorIsNil) t.bootstrapped = false t.prepared = false t.Env = nil }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) { if !t.HasProvisioner { c.Skip("HasProvisioner is false; cannot test deployment") } current := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } other := current other.Series = "quantal" if current == other { other.Series = "precise" } dummyCfg := dummy.SampleConfig().Merge(coretesting.Attrs{ "controller": false, "name": "dummy storage", }) args := t.prepareForBootstrapParams(c) args.BaseConfig = dummyCfg dummyenv, err := environs.Prepare(envtesting.BootstrapContext(c), jujuclienttesting.NewMemStore(), args, ) c.Assert(err, jc.ErrorIsNil) defer dummyenv.Destroy() t.Destroy(c) attrs := t.TestConfig.Merge(coretesting.Attrs{ "name": "livetests", "default-series": other.Series, }) args.BaseConfig = attrs env, err := environs.Prepare(envtesting.BootstrapContext(c), t.ControllerStore, args) c.Assert(err, jc.ErrorIsNil) defer environs.Destroy("livetests", env, t.ControllerStore) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) st := t.Env.(jujutesting.GetStater).GetStateInAPIServer() // Wait for machine agent to come up on the bootstrap // machine and ensure it deployed the proper series. m0, err := st.Machine("0") c.Assert(err, jc.ErrorIsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
func destroyPreparedEnvironProductionFunc( ctx *cmd.Context, env environs.Environ, store configstore.Storage, action string, ) { ctx.Infof("%s failed, destroying environment", action) if err := environs.Destroy(env, store); err != nil { logger.Errorf("the environment could not be destroyed: %v", err) } }
// Run implements Command.Run func (c *destroyCommand) Run(ctx *cmd.Context) error { store, err := configstore.Default() if err != nil { return errors.Annotate(err, "cannot open system info storage") } cfgInfo, err := store.ReadInfo(c.systemName) if err != nil { return errors.Annotate(err, "cannot read system info") } // Verify that we're destroying a system apiEndpoint := cfgInfo.APIEndpoint() if apiEndpoint.ServerUUID != "" && apiEndpoint.EnvironUUID != apiEndpoint.ServerUUID { return errors.Errorf("%q is not a system; use juju environment destroy to destroy it", c.systemName) } if !c.assumeYes { if err = confirmDestruction(ctx, c.systemName); err != nil { return err } } // Attempt to connect to the API. If we can't, fail the destroy. Users will // need to use the system kill command if we can't connect. api, err := c.getSystemAPI() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil) } defer api.Close() // Obtain bootstrap / system environ information systemEnviron, err := c.getSystemEnviron(cfgInfo, api) if err != nil { return errors.Annotate(err, "cannot obtain bootstrap information") } // Attempt to destroy the system. err = api.DestroySystem(c.destroyEnvs, false) if params.IsCodeNotImplemented(err) { // Fall back to using the client endpoint to destroy the system, // sending the info we were already able to collect. return c.destroySystemViaClient(ctx, cfgInfo, systemEnviron, store) } if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy system"), ctx, api) } return environs.Destroy(systemEnviron, store) }
// destroyControllerViaClient attempts to destroy the controller using the client // endpoint for older juju controllers which do not implement controller.DestroyController func (c *destroyCommand) destroyControllerViaClient(ctx *cmd.Context, info configstore.EnvironInfo, controllerEnviron environs.Environ, store configstore.Storage) error { api, err := c.getClientAPI() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil) } defer api.Close() err = api.DestroyEnvironment() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, nil) } return environs.Destroy(controllerEnviron, store) }
// Run implements Command.Run func (c *destroyCommand) Run(ctx *cmd.Context) error { controllerName := c.ControllerName() store := c.ClientStore() controllerDetails, err := store.ControllerByName(controllerName) if err != nil { return errors.Annotate(err, "cannot read controller info") } if !c.assumeYes { if err = confirmDestruction(ctx, c.ControllerName()); err != nil { return err } } // Attempt to connect to the API. If we can't, fail the destroy. Users will // need to use the controller kill command if we can't connect. api, err := c.getControllerAPI() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil) } defer api.Close() // Obtain controller environ so we can clean up afterwards. controllerEnviron, err := c.getControllerEnviron(store, controllerName, api) if err != nil { return errors.Annotate(err, "getting controller environ") } // Attempt to destroy the controller. err = api.DestroyController(c.destroyModels) if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, api) } ctx.Infof("Destroying controller %q", c.ControllerName()) if c.destroyModels { ctx.Infof("Waiting for hosted model resources to be reclaimed.") updateStatus := newTimedStatusUpdater(ctx, api, controllerDetails.ControllerUUID) for ctrStatus, modelsStatus := updateStatus(0); hasUnDeadModels(modelsStatus); ctrStatus, modelsStatus = updateStatus(2 * time.Second) { ctx.Infof(fmtCtrStatus(ctrStatus)) for _, model := range modelsStatus { ctx.Verbosef(fmtModelStatus(model)) } } ctx.Infof("All hosted models reclaimed, cleaning up controller machines") } return environs.Destroy(c.ControllerName(), controllerEnviron, store) }
// killSystemViaClient attempts to kill the system using the client // endpoint for older juju systems which do not implement systemmanager.DestroySystem func (c *killCommand) killSystemViaClient(ctx *cmd.Context, info configstore.EnvironInfo, systemEnviron environs.Environ, store configstore.Storage) error { api, err := c.getClientAPI() if err != nil { defer api.Close() } if api != nil { err = api.DestroyEnvironment() if err != nil { ctx.Infof("Unable to destroy system through the API: %s. Destroying through provider.", err) } } return environs.Destroy(systemEnviron, store) }
func (t *Tests) TestBootstrap(c *gc.C) { e := t.Prepare(c) t.UploadFakeTools(c, e.Storage()) err := bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) info, apiInfo, err := e.StateInfo() c.Check(info.Addrs, gc.Not(gc.HasLen), 0) c.Check(apiInfo.Addrs, gc.Not(gc.HasLen), 0) err = bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") e2 := t.Open(c) t.UploadFakeTools(c, e2.Storage()) err = bootstrap.EnsureNotBootstrapped(e2) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") checkSameInfo := func(a, b *state.Info) { c.Check(a.Addrs, jc.SameContents, b.Addrs) c.Check(a.CACert, gc.DeepEquals, b.CACert) } info2, apiInfo2, err := e2.StateInfo() checkSameInfo(info2, info) c.Check(apiInfo2, gc.DeepEquals, apiInfo) err = environs.Destroy(e2, t.ConfigStore) c.Assert(err, gc.IsNil) // Prepare again because Destroy invalidates old environments. e3 := t.Prepare(c) t.UploadFakeTools(c, e3.Storage()) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e3, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) { if !t.HasProvisioner { c.Skip("HasProvisioner is false; cannot test deployment") } current := version.Current other := current other.Series = "quantal" if current == other { other.Series = "precise" } dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{ "state-server": false, "name": "dummy storage", })) dummyenv, err := environs.Prepare(dummyCfg, envtesting.BootstrapContext(c), configstore.NewMem()) c.Assert(err, jc.ErrorIsNil) defer dummyenv.Destroy() t.Destroy(c) attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series}) cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, jc.ErrorIsNil) env, err := environs.Prepare(cfg, envtesting.BootstrapContext(c), t.ConfigStore) c.Assert(err, jc.ErrorIsNil) defer environs.Destroy(env, t.ConfigStore) err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) st := t.Env.(jujutesting.GetStater).GetStateInAPIServer() // Wait for machine agent to come up on the bootstrap // machine and ensure it deployed the proper series. m0, err := st.Machine("0") c.Assert(err, jc.ErrorIsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
// Run implements Command.Run func (c *destroyCommand) Run(ctx *cmd.Context) error { controllerName := c.ControllerName() store := c.ClientStore() if !c.assumeYes { if err := confirmDestruction(ctx, c.ControllerName()); err != nil { return err } } // Attempt to connect to the API. If we can't, fail the destroy. Users will // need to use the controller kill command if we can't connect. api, err := c.getControllerAPI() if err != nil { return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil) } defer api.Close() // Obtain controller environ so we can clean up afterwards. controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api) if err != nil { return errors.Annotate(err, "getting controller environ") } for { // Attempt to destroy the controller. ctx.Infof("Destroying controller") var hasHostedModels bool err = api.DestroyController(c.destroyModels) if err != nil { if params.IsCodeHasHostedModels(err) { hasHostedModels = true } else { return c.ensureUserFriendlyErrorLog( errors.Annotate(err, "cannot destroy controller"), ctx, api, ) } } updateStatus := newTimedStatusUpdater(ctx, api, controllerEnviron.Config().UUID(), clock.WallClock) ctrStatus, modelsStatus := updateStatus(0) if !c.destroyModels { if err := c.checkNoAliveHostedModels(ctx, modelsStatus); err != nil { return errors.Trace(err) } if hasHostedModels && !hasUnDeadModels(modelsStatus) { // When we called DestroyController before, we were // informed that there were hosted models remaining. // When we checked just now, there were none. We should // try destroying again. continue } } // Even if we've not just requested for hosted models to be destroyed, // there may be some being destroyed already. We need to wait for them. ctx.Infof("Waiting for hosted model resources to be reclaimed") for ; hasUnDeadModels(modelsStatus); ctrStatus, modelsStatus = updateStatus(2 * time.Second) { ctx.Infof(fmtCtrStatus(ctrStatus)) for _, model := range modelsStatus { ctx.Verbosef(fmtModelStatus(model)) } } ctx.Infof("All hosted models reclaimed, cleaning up controller machines") return environs.Destroy(c.ControllerName(), controllerEnviron, store) } }
// Run implements Command.Run func (c *killCommand) Run(ctx *cmd.Context) error { store, err := configstore.Default() if err != nil { return errors.Annotate(err, "cannot open controller info storage") } cfgInfo, err := store.ReadInfo(c.ModelName()) if err != nil { return errors.Annotate(err, "cannot read controller info") } // Verify that we're destroying a controller apiEndpoint := cfgInfo.APIEndpoint() if apiEndpoint.ServerUUID != "" && apiEndpoint.ModelUUID != apiEndpoint.ServerUUID { return errors.Errorf("%q is not a controller; use juju model destroy to destroy it", c.ModelName()) } if !c.assumeYes { if err = confirmDestruction(ctx, c.ModelName()); err != nil { return err } } // Attempt to connect to the API. api, err := c.getControllerAPI() switch { case err == nil: defer api.Close() case errors.Cause(err) == common.ErrPerm: return errors.Annotate(err, "cannot destroy controller") default: if errors.Cause(err) != modelcmd.ErrConnTimedOut { logger.Debugf("unable to open api: %s", err) } ctx.Infof("Unable to open API: %s\n", err) api = nil } // Obtain bootstrap / controller environ information controllerEnviron, err := c.getControllerEnviron(cfgInfo, api) if err != nil { return errors.Annotate(err, "cannot obtain bootstrap information") } // If we were unable to connect to the API, just destroy the controller through // the environs interface. if api == nil { ctx.Infof("Unable to connect to the API server. Destroying through provider.") return environs.Destroy(controllerEnviron, store) } // Attempt to destroy the controller and all environments. err = api.DestroyController(true) if err != nil { ctx.Infof("Unable to destroy controller through the API: %s. Destroying through provider.", err) return environs.Destroy(controllerEnviron, store) } ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", c.ModelName()) updateStatus := newTimedStatusUpdater(ctx, api, apiEndpoint.ModelUUID) for ctrStatus, envsStatus := updateStatus(0); hasUnDeadEnvirons(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) { ctx.Infof(fmtCtrStatus(ctrStatus)) for _, envStatus := range envsStatus { ctx.Verbosef(fmtEnvStatus(envStatus)) } } ctx.Infof("All hosted models reclaimed, cleaning up controller machines") return environs.Destroy(controllerEnviron, store) }
func (c *destroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) { store, err := configstore.Default() if err != nil { return errors.Annotate(err, "cannot open environment info storage") } cfgInfo, err := store.ReadInfo(c.EnvName()) if err != nil { return errors.Annotate(err, "cannot read environment info") } var hasBootstrapCfg bool var serverEnviron environs.Environ if bootstrapCfg := cfgInfo.BootstrapConfig(); bootstrapCfg != nil { hasBootstrapCfg = true serverEnviron, err = getServerEnv(bootstrapCfg) if err != nil { return errors.Trace(err) } } if c.force { if hasBootstrapCfg { // If --force is supplied on a server environment, then don't // attempt to use the API. This is necessary to destroy broken // environments, where the API server is inaccessible or faulty. return environs.Destroy(serverEnviron, store) } else { // Force only makes sense on the server environment. return errors.Errorf("cannot force destroy environment without bootstrap information") } } apiclient, err := c.NewAPIClient() if err != nil { if errors.IsNotFound(err) { logger.Warningf("environment not found, removing config file") ctx.Infof("environment not found, removing config file") return environs.DestroyInfo(c.EnvName(), store) } return errors.Annotate(err, "cannot connect to API") } defer apiclient.Close() info, err := apiclient.EnvironmentInfo() if err != nil { return errors.Annotate(err, "cannot get information for environment") } if !c.assumeYes { fmt.Fprintf(ctx.Stdout, destroyEnvMsg, c.EnvName(), info.ProviderType) scanner := bufio.NewScanner(ctx.Stdin) scanner.Scan() err := scanner.Err() if err != nil && err != io.EOF { return errors.Annotate(err, "environment destruction aborted") } answer := strings.ToLower(scanner.Text()) if answer != "y" && answer != "yes" { return stderrors.New("environment destruction aborted") } } if info.UUID == info.ServerUUID { if !hasBootstrapCfg { // serverEnviron will be nil as we didn't have the jenv bootstrap // config to build it. But we do have a connection to the API // server, so get the config from there. bootstrapCfg, err := apiclient.EnvironmentGet() if err != nil { return errors.Annotate(err, "environment destruction failed") } serverEnviron, err = getServerEnv(bootstrapCfg) if err != nil { return errors.Annotate(err, "environment destruction failed") } } if err := c.destroyEnv(apiclient); err != nil { return errors.Annotate(err, "environment destruction failed") } if err := environs.Destroy(serverEnviron, store); err != nil { return errors.Annotate(err, "environment destruction failed") } return environs.DestroyInfo(c.EnvName(), store) } // If this is not the server environment, there is no bootstrap info and // we do not call Destroy on the provider. Destroying the environment via // the API and cleaning up the jenv file is sufficient. if err := c.destroyEnv(apiclient); err != nil { errors.Annotate(err, "cannot destroy environment") } return environs.DestroyInfo(c.EnvName(), store) }
// Run implements Command.Run func (c *killCommand) Run(ctx *cmd.Context) error { if c.apiDialerFunc == nil { c.apiDialerFunc = c.NewAPIRoot } store, err := configstore.Default() if err != nil { return errors.Annotate(err, "cannot open system info storage") } cfgInfo, err := store.ReadInfo(c.systemName) if err != nil { return errors.Annotate(err, "cannot read system info") } // Verify that we're destroying a system apiEndpoint := cfgInfo.APIEndpoint() if apiEndpoint.ServerUUID != "" && apiEndpoint.EnvironUUID != apiEndpoint.ServerUUID { return errors.Errorf("%q is not a system; use juju environment destroy to destroy it", c.systemName) } if !c.assumeYes { if err = confirmDestruction(ctx, c.systemName); err != nil { return err } } // Attempt to connect to the API. api, err := c.getSystemAPI(cfgInfo) switch { case err == nil: defer api.Close() case errors.Cause(err) == common.ErrPerm: return errors.Annotate(err, "cannot destroy system") default: if err != ErrConnTimedOut { logger.Debugf("unable to open api: %s", err) } ctx.Infof("Unable to open API: %s\n", err) api = nil } // Obtain bootstrap / system environ information systemEnviron, err := c.getSystemEnviron(cfgInfo, api) if err != nil { return errors.Annotate(err, "cannot obtain bootstrap information") } // If we were unable to connect to the API, just destroy the system through // the environs interface. if api == nil { return environs.Destroy(systemEnviron, store) } // Attempt to destroy the system with destroyEnvs and ignoreBlocks = true err = api.DestroySystem(true, true) if params.IsCodeNotImplemented(err) { // Fall back to using the client endpoint to destroy the system, // sending the info we were already able to collect. return c.killSystemViaClient(ctx, cfgInfo, systemEnviron, store) } if err != nil { ctx.Infof("Unable to destroy system through the API: %s. Destroying through provider.", err) } return environs.Destroy(systemEnviron, store) }