github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/storage/detach.go (about) 1 // Copyright 2017 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 10 "github.com/juju/juju/apiserver/params" 11 jujucmd "github.com/juju/juju/cmd" 12 "github.com/juju/juju/cmd/juju/common" 13 "github.com/juju/juju/cmd/modelcmd" 14 ) 15 16 // NewDetachStorageCommandWithAPI returns a command 17 // used to detach storage from application units. 18 func NewDetachStorageCommandWithAPI() cmd.Command { 19 cmd := &detachStorageCommand{} 20 cmd.newEntityDetacherCloser = func() (EntityDetacherCloser, error) { 21 return cmd.NewStorageAPI() 22 } 23 return modelcmd.Wrap(cmd) 24 } 25 26 // NewDetachStorageCommand returns a command used to 27 // detach storage from application units. 28 func NewDetachStorageCommand(new NewEntityDetacherCloserFunc) cmd.Command { 29 cmd := &detachStorageCommand{} 30 cmd.newEntityDetacherCloser = new 31 return modelcmd.Wrap(cmd) 32 } 33 34 const ( 35 detachStorageCommandDoc = ` 36 Detaches storage from units. Specify one or more unit/application storage IDs, 37 as output by "juju storage". The storage will remain in the model until it is 38 removed by an operator. 39 40 Examples: 41 juju detach-storage pgdata/0 42 ` 43 44 detachStorageCommandArgs = `<storage> [<storage> ...]` 45 ) 46 47 // detachStorageCommand detaches storage instances. 48 type detachStorageCommand struct { 49 StorageCommandBase 50 modelcmd.IAASOnlyCommand 51 newEntityDetacherCloser NewEntityDetacherCloserFunc 52 storageIds []string 53 } 54 55 // Init implements Command.Init. 56 func (c *detachStorageCommand) Init(args []string) error { 57 if len(args) < 1 { 58 return errors.New("detach-storage requires at least one storage ID") 59 } 60 c.storageIds = args 61 return nil 62 } 63 64 // Info implements Command.Info. 65 func (c *detachStorageCommand) Info() *cmd.Info { 66 return jujucmd.Info(&cmd.Info{ 67 Name: "detach-storage", 68 Purpose: "Detaches storage from units.", 69 Doc: detachStorageCommandDoc, 70 Args: detachStorageCommandArgs, 71 }) 72 } 73 74 // Run implements Command.Run. 75 func (c *detachStorageCommand) Run(ctx *cmd.Context) error { 76 detacher, err := c.newEntityDetacherCloser() 77 if err != nil { 78 return errors.Trace(err) 79 } 80 defer detacher.Close() 81 82 results, err := detacher.Detach(c.storageIds) 83 if err != nil { 84 if params.IsCodeUnauthorized(err) { 85 common.PermissionsMessage(ctx.Stderr, "detach storage") 86 } 87 return err 88 } 89 for i, result := range results { 90 if result.Error == nil { 91 ctx.Infof("detaching %s", c.storageIds[i]) 92 } 93 } 94 anyFailed := false 95 for i, result := range results { 96 if result.Error != nil { 97 ctx.Infof("failed to detach %s: %s", c.storageIds[i], result.Error) 98 anyFailed = true 99 } 100 } 101 if anyFailed { 102 return cmd.ErrSilent 103 } 104 return nil 105 } 106 107 // NewEntityDetacherCloser is the type of a function that returns an 108 // EntityDetacherCloser. 109 type NewEntityDetacherCloserFunc func() (EntityDetacherCloser, error) 110 111 // EntityDetacherCloser extends EntityDetacher with a Closer method. 112 type EntityDetacherCloser interface { 113 EntityDetacher 114 Close() error 115 } 116 117 // EntityDetacher defines an interface for detaching storage with the 118 // specified IDs. 119 type EntityDetacher interface { 120 Detach([]string) ([]params.ErrorResult, error) 121 }