~nskaggs/+junk/xenial-test

« back to all changes in this revision

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

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for infos.
 
3
 
 
4
package model
 
5
 
 
6
import (
 
7
        "fmt"
 
8
 
 
9
        "github.com/juju/cmd"
 
10
        "github.com/juju/errors"
 
11
        "github.com/juju/loggo"
 
12
        "launchpad.net/gnuflag"
 
13
 
 
14
        "github.com/juju/juju/api/modelmanager"
 
15
        "github.com/juju/juju/apiserver/params"
 
16
        jujucmd "github.com/juju/juju/cmd"
 
17
        "github.com/juju/juju/cmd/juju/block"
 
18
        "github.com/juju/juju/cmd/modelcmd"
 
19
)
 
20
 
 
21
var logger = loggo.GetLogger("juju.cmd.juju.model")
 
22
 
 
23
// NewDestroyCommand returns a command used to destroy a model.
 
24
func NewDestroyCommand() cmd.Command {
 
25
        return modelcmd.Wrap(
 
26
                &destroyCommand{},
 
27
                modelcmd.ModelSkipDefault,
 
28
                modelcmd.ModelSkipFlags,
 
29
        )
 
30
}
 
31
 
 
32
// destroyCommand destroys the specified model.
 
33
type destroyCommand struct {
 
34
        modelcmd.ModelCommandBase
 
35
        envName   string
 
36
        assumeYes bool
 
37
        api       DestroyModelAPI
 
38
}
 
39
 
 
40
var destroyDoc = `
 
41
Destroys the specified model. This will result in the non-recoverable
 
42
removal of all the units operating in the model and any resources stored
 
43
there. Due to the irreversible nature of the command, it will prompt for
 
44
confirmation (unless overridden with the '-y' option) before taking any
 
45
action.
 
46
 
 
47
Examples:
 
48
 
 
49
      juju destroy-model test
 
50
      juju destroy-model -y mymodel
 
51
 
 
52
See also: destroy-controller
 
53
`
 
54
var destroyEnvMsg = `
 
55
WARNING! This command will destroy the %q model.
 
56
This includes all machines, applications, data and other resources.
 
57
 
 
58
Continue [y/N]? `[1:]
 
59
 
 
60
// DestroyModelAPI defines the methods on the modelmanager
 
61
// API that the destroy command calls. It is exported for mocking in tests.
 
62
type DestroyModelAPI interface {
 
63
        Close() error
 
64
        DestroyModel() error
 
65
}
 
66
 
 
67
// Info implements Command.Info.
 
68
func (c *destroyCommand) Info() *cmd.Info {
 
69
        return &cmd.Info{
 
70
                Name:    "destroy-model",
 
71
                Args:    "[<controller name>:]<model name>",
 
72
                Purpose: "Terminate all machines and resources for a non-controller model.",
 
73
                Doc:     destroyDoc,
 
74
        }
 
75
}
 
76
 
 
77
// SetFlags implements Command.SetFlags.
 
78
func (c *destroyCommand) SetFlags(f *gnuflag.FlagSet) {
 
79
        f.BoolVar(&c.assumeYes, "y", false, "Do not prompt for confirmation")
 
80
        f.BoolVar(&c.assumeYes, "yes", false, "")
 
81
}
 
82
 
 
83
// Init implements Command.Init.
 
84
func (c *destroyCommand) Init(args []string) error {
 
85
        switch len(args) {
 
86
        case 0:
 
87
                return errors.New("no model specified")
 
88
        case 1:
 
89
                return c.SetModelName(args[0])
 
90
        default:
 
91
                return cmd.CheckEmpty(args[1:])
 
92
        }
 
93
}
 
94
 
 
95
func (c *destroyCommand) getAPI() (DestroyModelAPI, error) {
 
96
        if c.api != nil {
 
97
                return c.api, nil
 
98
        }
 
99
        root, err := c.NewAPIRoot()
 
100
        if err != nil {
 
101
                return nil, errors.Trace(err)
 
102
        }
 
103
        return modelmanager.NewClient(root), nil
 
104
}
 
105
 
 
106
// Run implements Command.Run
 
107
func (c *destroyCommand) Run(ctx *cmd.Context) error {
 
108
        store := c.ClientStore()
 
109
        controllerName := c.ControllerName()
 
110
        modelName := c.ModelName()
 
111
 
 
112
        controllerDetails, err := store.ControllerByName(controllerName)
 
113
        if err != nil {
 
114
                return errors.Annotate(err, "cannot read controller details")
 
115
        }
 
116
        modelDetails, err := store.ModelByName(controllerName, modelName)
 
117
        if err != nil {
 
118
                return errors.Annotate(err, "cannot read model info")
 
119
        }
 
120
        if modelDetails.ModelUUID == controllerDetails.ControllerUUID {
 
121
                return errors.Errorf("%q is a controller; use 'juju destroy-controller' to destroy it", modelName)
 
122
        }
 
123
 
 
124
        if !c.assumeYes {
 
125
                fmt.Fprintf(ctx.Stdout, destroyEnvMsg, modelName)
 
126
 
 
127
                if err := jujucmd.UserConfirmYes(ctx); err != nil {
 
128
                        return errors.Annotate(err, "model destruction")
 
129
                }
 
130
        }
 
131
 
 
132
        // Attempt to connect to the API.  If we can't, fail the destroy.
 
133
        api, err := c.getAPI()
 
134
        if err != nil {
 
135
                return errors.Annotate(err, "cannot connect to API")
 
136
        }
 
137
        defer api.Close()
 
138
 
 
139
        // Attempt to destroy the model.
 
140
        err = api.DestroyModel()
 
141
        if err != nil {
 
142
                return c.handleError(errors.Annotate(err, "cannot destroy model"), modelName)
 
143
        }
 
144
 
 
145
        err = store.RemoveModel(controllerName, modelName)
 
146
        if err != nil && !errors.IsNotFound(err) {
 
147
                return errors.Trace(err)
 
148
        }
 
149
        return nil
 
150
}
 
151
 
 
152
func (c *destroyCommand) handleError(err error, modelName string) error {
 
153
        if err == nil {
 
154
                return nil
 
155
        }
 
156
        if params.IsCodeOperationBlocked(err) {
 
157
                return block.ProcessBlockedError(err, block.BlockDestroy)
 
158
        }
 
159
        logger.Errorf(`failed to destroy model %q`, modelName)
 
160
        return err
 
161
}