~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/controller/destroy.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
        "github.com/juju/juju/cmd/modelcmd"
25
25
        "github.com/juju/juju/environs"
26
26
        "github.com/juju/juju/environs/config"
27
 
        "github.com/juju/juju/environs/configstore"
 
27
        "github.com/juju/juju/jujuclient"
28
28
)
29
29
 
30
30
// NewDestroyCommand returns a command to destroy a controller.
91
91
 
92
92
// Run implements Command.Run
93
93
func (c *destroyCommand) Run(ctx *cmd.Context) error {
94
 
        store, err := configstore.Default()
95
 
        if err != nil {
96
 
                return errors.Annotate(err, "cannot open controller info storage")
97
 
        }
98
 
 
99
94
        controllerName := c.ControllerName()
100
 
        cfgInfo, err := store.ReadInfo(configstore.EnvironInfoName(
101
 
                controllerName, configstore.AdminModelName(controllerName),
102
 
        ))
 
95
        store := c.ClientStore()
 
96
        controllerDetails, err := store.ControllerByName(controllerName)
103
97
        if err != nil {
104
98
                return errors.Annotate(err, "cannot read controller info")
105
99
        }
106
100
 
107
 
        // Verify that we're destroying a controller
108
 
        apiEndpoint := cfgInfo.APIEndpoint()
109
 
        if apiEndpoint.ServerUUID != "" && apiEndpoint.ModelUUID != apiEndpoint.ServerUUID {
110
 
                return errors.Errorf("%q is not a controller; use juju destroy-model to destroy it", c.ControllerName())
111
 
        }
112
 
 
113
101
        if !c.assumeYes {
114
102
                if err = confirmDestruction(ctx, c.ControllerName()); err != nil {
115
103
                        return err
124
112
        }
125
113
        defer api.Close()
126
114
 
127
 
        // Obtain bootstrap / controller environ information
128
 
        controllerEnviron, err := c.getControllerModel(cfgInfo, api)
 
115
        // Obtain controller environ so we can clean up afterwards.
 
116
        controllerEnviron, err := c.getControllerEnviron(store, controllerName, api)
129
117
        if err != nil {
130
 
                return errors.Annotate(err, "cannot obtain bootstrap information")
 
118
                return errors.Annotate(err, "getting controller environ")
131
119
        }
132
120
 
133
121
        // Attempt to destroy the controller.
140
128
        if c.destroyModels {
141
129
                ctx.Infof("Waiting for hosted model resources to be reclaimed.")
142
130
 
143
 
                updateStatus := newTimedStatusUpdater(ctx, api, apiEndpoint.ModelUUID)
 
131
                updateStatus := newTimedStatusUpdater(ctx, api, controllerDetails.ControllerUUID)
144
132
                for ctrStatus, modelsStatus := updateStatus(0); hasUnDeadModels(modelsStatus); ctrStatus, modelsStatus = updateStatus(2 * time.Second) {
145
133
                        ctx.Infof(fmtCtrStatus(ctrStatus))
146
134
                        for _, model := range modelsStatus {
150
138
 
151
139
                ctx.Infof("All hosted models reclaimed, cleaning up controller machines")
152
140
        }
153
 
        return environs.Destroy(c.ControllerName(), controllerEnviron, store, c.ClientStore())
 
141
        return environs.Destroy(c.ControllerName(), controllerEnviron, store)
154
142
}
155
143
 
156
144
// ensureUserFriendlyErrorLog ensures that error will be logged and displayed
255
243
        return controller.NewClient(root), nil
256
244
}
257
245
 
258
 
func (c *destroyCommandBase) getClientAPI() (destroyClientAPI, error) {
259
 
        if c.clientapi != nil {
260
 
                return c.clientapi, nil
261
 
        }
262
 
        root, err := c.NewAPIRoot()
263
 
        if err != nil {
264
 
                return nil, errors.Trace(err)
265
 
        }
266
 
        return root.Client(), nil
267
 
}
268
 
 
269
246
// SetFlags implements Command.SetFlags.
270
247
func (c *destroyCommandBase) SetFlags(f *gnuflag.FlagSet) {
271
248
        f.BoolVar(&c.assumeYes, "y", false, "Do not ask for confirmation")
284
261
        }
285
262
}
286
263
 
287
 
// getControllerModel gets the bootstrap information required to destroy the
288
 
// model by first checking the config store, then querying the API if
289
 
// the information is not in the store.
290
 
func (c *destroyCommandBase) getControllerModel(info configstore.EnvironInfo, sysAPI destroyControllerAPI) (_ environs.Environ, err error) {
291
 
        bootstrapCfg := info.BootstrapConfig()
292
 
        if bootstrapCfg == nil {
 
264
// getControllerEnviron returns the Environ for the controller model.
 
265
//
 
266
// getControllerEnviron gets the information required to get the
 
267
// Environ by first checking the config store, then querying the
 
268
// API if the information is not in the store.
 
269
func (c *destroyCommandBase) getControllerEnviron(
 
270
        store jujuclient.ClientStore, controllerName string, sysAPI destroyControllerAPI,
 
271
) (_ environs.Environ, err error) {
 
272
        cfg, err := modelcmd.NewGetBootstrapConfigFunc(store)(controllerName)
 
273
        if errors.IsNotFound(err) {
293
274
                if sysAPI == nil {
294
 
                        return nil, errors.New("unable to get bootstrap information from API")
295
 
                }
296
 
                bootstrapCfg, err = sysAPI.ModelConfig()
 
275
                        return nil, errors.New(
 
276
                                "unable to get bootstrap information from client store or API",
 
277
                        )
 
278
                }
 
279
                bootstrapConfig, err := sysAPI.ModelConfig()
 
280
                if err != nil {
 
281
                        return nil, errors.Annotate(err, "getting bootstrap config from API")
 
282
                }
 
283
                cfg, err = config.New(config.NoDefaults, bootstrapConfig)
297
284
                if err != nil {
298
285
                        return nil, errors.Trace(err)
299
286
                }
300
 
        }
301
 
 
302
 
        cfg, err := config.New(config.NoDefaults, bootstrapCfg)
303
 
        if err != nil {
304
 
                return nil, errors.Trace(err)
 
287
        } else if err != nil {
 
288
                return nil, errors.Annotate(err, "getting bootstrap config from client store")
305
289
        }
306
290
        return environs.New(cfg)
307
291
}