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  }