github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/storage/attach.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  // NewAttachStorageCommandWithAPI returns a command
    17  // used to attach storage to application units.
    18  func NewAttachStorageCommandWithAPI() cmd.Command {
    19  	cmd := &attachStorageCommand{}
    20  	cmd.newEntityAttacherCloser = func() (EntityAttacherCloser, error) {
    21  		return cmd.NewStorageAPI()
    22  	}
    23  	return modelcmd.Wrap(cmd)
    24  }
    25  
    26  // NewAttachStorageCommand returns a command used to
    27  // attach storage to application units.
    28  func NewAttachStorageCommand(new NewEntityAttacherCloserFunc) cmd.Command {
    29  	cmd := &attachStorageCommand{}
    30  	cmd.newEntityAttacherCloser = new
    31  	return modelcmd.Wrap(cmd)
    32  }
    33  
    34  const (
    35  	attachStorageCommandDoc = `
    36  Attach existing storage to a unit. Specify a unit
    37  and one or more storage IDs to attach to it.
    38  
    39  Examples:
    40      juju attach-storage postgresql/1 pgdata/0
    41  `
    42  
    43  	attachStorageCommandArgs = `<unit> <storage> [<storage> ...]`
    44  )
    45  
    46  // attachStorageCommand adds unit storage instances dynamically.
    47  type attachStorageCommand struct {
    48  	StorageCommandBase
    49  	modelcmd.IAASOnlyCommand
    50  	newEntityAttacherCloser NewEntityAttacherCloserFunc
    51  	unitId                  string
    52  	storageIds              []string
    53  }
    54  
    55  // Init implements Command.Init.
    56  func (c *attachStorageCommand) Init(args []string) error {
    57  	if len(args) < 2 {
    58  		return errors.New("attach-storage requires a unit ID and at least one storage ID")
    59  	}
    60  	c.unitId = args[0]
    61  	c.storageIds = args[1:]
    62  	return nil
    63  }
    64  
    65  // Info implements Command.Info.
    66  func (c *attachStorageCommand) Info() *cmd.Info {
    67  	return jujucmd.Info(&cmd.Info{
    68  		Name:    "attach-storage",
    69  		Purpose: "Attaches existing storage to a unit.",
    70  		Doc:     attachStorageCommandDoc,
    71  		Args:    attachStorageCommandArgs,
    72  	})
    73  }
    74  
    75  // Run implements Command.Run.
    76  func (c *attachStorageCommand) Run(ctx *cmd.Context) error {
    77  	attacher, err := c.newEntityAttacherCloser()
    78  	if err != nil {
    79  		return err
    80  	}
    81  	defer attacher.Close()
    82  
    83  	results, err := attacher.Attach(c.unitId, c.storageIds)
    84  	if err != nil {
    85  		if params.IsCodeUnauthorized(err) {
    86  			common.PermissionsMessage(ctx.Stderr, "attach storage")
    87  		}
    88  		return errors.Trace(err)
    89  	}
    90  	for i, result := range results {
    91  		if result.Error == nil {
    92  			ctx.Infof("attaching %s to %s", c.storageIds[i], c.unitId)
    93  		}
    94  	}
    95  	var anyFailed bool
    96  	for i, result := range results {
    97  		if result.Error != nil {
    98  			ctx.Infof("failed to attach %s to %s: %s", c.storageIds[i], c.unitId, result.Error)
    99  			anyFailed = true
   100  		}
   101  	}
   102  	if anyFailed {
   103  		return cmd.ErrSilent
   104  	}
   105  	return nil
   106  }
   107  
   108  // NewEntityAttacherCloser is the type of a function that returns an
   109  // EntityAttacherCloser.
   110  type NewEntityAttacherCloserFunc func() (EntityAttacherCloser, error)
   111  
   112  // EntityAttacherCloser extends EntityAttacher with a Closer method.
   113  type EntityAttacherCloser interface {
   114  	EntityAttacher
   115  	Close() error
   116  }
   117  
   118  // EntityAttacher defines an interface for attaching storage with the
   119  // specified IDs to a unit.
   120  type EntityAttacher interface {
   121  	Attach(string, []string) ([]params.ErrorResult, error)
   122  }