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