github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/storage/remove.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 11 "github.com/juju/juju/apiserver/params" 12 jujucmd "github.com/juju/juju/cmd" 13 "github.com/juju/juju/cmd/juju/common" 14 "github.com/juju/juju/cmd/modelcmd" 15 ) 16 17 // NewRemoveStorageCommandWithAPI returns a command 18 // used to remove storage from the model. 19 func NewRemoveStorageCommandWithAPI() cmd.Command { 20 cmd := &removeStorageCommand{} 21 cmd.newStorageRemoverCloser = func() (StorageRemoverCloser, error) { 22 return cmd.NewStorageAPI() 23 } 24 return modelcmd.Wrap(cmd) 25 } 26 27 const ( 28 removeStorageCommandDoc = ` 29 Removes storage from the model. Specify one or more 30 storage IDs, as output by "juju storage". 31 32 By default, remove-storage will fail if the storage 33 is attached to any units. To override this behaviour, 34 you can use "juju remove-storage --force". 35 36 Examples: 37 # Remove the detached storage pgdata/0. 38 juju remove-storage pgdata/0 39 40 # Remove the possibly attached storage pgdata/0. 41 juju remove-storage --force pgdata/0 42 43 # Remove the storage pgdata/0, without destroying 44 # the corresponding cloud storage. 45 juju remove-storage --no-destroy pgdata/0 46 ` 47 removeStorageCommandArgs = `<storage> [<storage> ...]` 48 ) 49 50 type removeStorageCommand struct { 51 StorageCommandBase 52 modelcmd.IAASOnlyCommand 53 newStorageRemoverCloser NewStorageRemoverCloserFunc 54 storageIds []string 55 force bool 56 noDestroy bool 57 } 58 59 // Info implements Command.Info. 60 func (c *removeStorageCommand) Info() *cmd.Info { 61 return jujucmd.Info(&cmd.Info{ 62 Name: "remove-storage", 63 Purpose: "Removes storage from the model.", 64 Doc: removeStorageCommandDoc, 65 Args: removeStorageCommandArgs, 66 }) 67 } 68 69 func (c *removeStorageCommand) SetFlags(f *gnuflag.FlagSet) { 70 c.StorageCommandBase.SetFlags(f) 71 f.BoolVar(&c.force, "force", false, "Remove storage even if it is currently attached") 72 f.BoolVar(&c.noDestroy, "no-destroy", false, "Remove the storage without destroying it") 73 } 74 75 // Init implements Command.Init. 76 func (c *removeStorageCommand) Init(args []string) error { 77 if len(args) < 1 { 78 return errors.New("remove-storage requires at least one storage ID") 79 } 80 c.storageIds = args 81 return nil 82 } 83 84 // Run implements Command.Run. 85 func (c *removeStorageCommand) Run(ctx *cmd.Context) error { 86 remover, err := c.newStorageRemoverCloser() 87 if err != nil { 88 return errors.Trace(err) 89 } 90 defer remover.Close() 91 92 destroyAttachments := c.force 93 destroyStorage := !c.noDestroy 94 results, err := remover.Remove(c.storageIds, destroyAttachments, destroyStorage) 95 if err != nil { 96 if params.IsCodeUnauthorized(err) { 97 common.PermissionsMessage(ctx.Stderr, "remove storage") 98 } 99 return err 100 } 101 for i, result := range results { 102 if result.Error == nil { 103 ctx.Infof("removing %s", c.storageIds[i]) 104 } 105 } 106 anyFailed := false 107 anyAttached := false 108 for i, result := range results { 109 if result.Error != nil { 110 ctx.Infof("failed to remove %s: %s", c.storageIds[i], result.Error) 111 if params.IsCodeStorageAttached(result.Error) { 112 anyAttached = true 113 } 114 anyFailed = true 115 } 116 } 117 if anyAttached { 118 ctx.Infof(` 119 Use the --force option to remove attached storage, or use 120 "juju detach-storage" to explicitly detach the storage 121 before removing.`) 122 } 123 if anyFailed { 124 return cmd.ErrSilent 125 } 126 return nil 127 } 128 129 // NewStorageRemoverCloserFunc is the type of a function that returns an 130 // StorageRemoverCloser. 131 type NewStorageRemoverCloserFunc func() (StorageRemoverCloser, error) 132 133 // StorageRemoverCloser extends StorageRemover with a Closer method. 134 type StorageRemoverCloser interface { 135 StorageRemover 136 Close() error 137 } 138 139 // StorageRemover defines an interface for destroying storage instances 140 // with the specified IDs. 141 type StorageRemover interface { 142 Remove( 143 storageIds []string, 144 destroyAttachments, destroyStorage bool, 145 ) ([]params.ErrorResult, error) 146 }