github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/juju/model/grantrevoke.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package model
     5  
     6  import (
     7  	"github.com/juju/cmd"
     8  	"github.com/juju/errors"
     9  
    10  	"github.com/juju/juju/cmd/juju/block"
    11  	"github.com/juju/juju/cmd/modelcmd"
    12  	"github.com/juju/juju/permission"
    13  )
    14  
    15  var usageGrantSummary = `
    16  Grants access level to a Juju user for a model or controller.`[1:]
    17  
    18  var usageGrantDetails = `
    19  By default, the controller is the current controller.
    20  
    21  Users with read access are limited in what they can do with models:
    22  ` + "`juju models`, `juju machines`, and `juju status`" + `.
    23  
    24  Examples:
    25  Grant user 'joe' 'read' access to model 'mymodel':
    26  
    27      juju grant joe read mymodel
    28  
    29  Grant user 'jim' 'write' access to model 'mymodel':
    30  
    31      juju grant jim write mymodel
    32  
    33  Grant user 'sam' 'read' access to models 'model1' and 'model2':
    34  
    35      juju grant sam read model1 model2
    36  
    37  Grant user 'maria' 'add-model' access to the controller:
    38  
    39      juju grant maria add-model
    40  
    41  Valid access levels for models are:
    42      read
    43      write
    44      admin
    45  
    46  Valid access levels for controllers are:
    47      login
    48      add-model
    49      superuser
    50  
    51  See also: 
    52      revoke
    53      add-user`
    54  
    55  var usageRevokeSummary = `
    56  Revokes access from a Juju user for a model or controller`[1:]
    57  
    58  var usageRevokeDetails = `
    59  By default, the controller is the current controller.
    60  
    61  Revoking write access, from a user who has that permission, will leave
    62  that user with read access. Revoking read access, however, also revokes
    63  write access.
    64  
    65  Examples:
    66  Revoke 'read' (and 'write') access from user 'joe' for model 'mymodel':
    67  
    68      juju revoke joe read mymodel
    69  
    70  Revoke 'write' access from user 'sam' for models 'model1' and 'model2':
    71  
    72      juju revoke sam write model1 model2
    73  
    74  Revoke 'add-model' access from user 'maria' to the controller:
    75  
    76      juju revoke maria add-model
    77  
    78  See also: 
    79      grant`[1:]
    80  
    81  type accessCommand struct {
    82  	modelcmd.ControllerCommandBase
    83  
    84  	User       string
    85  	ModelNames []string
    86  	Access     string
    87  }
    88  
    89  // Init implements cmd.Command.
    90  func (c *accessCommand) Init(args []string) error {
    91  	if len(args) < 1 {
    92  		return errors.New("no user specified")
    93  	}
    94  
    95  	if len(args) < 2 {
    96  		return errors.New("no permission level specified")
    97  	}
    98  
    99  	c.User = args[0]
   100  	c.ModelNames = args[2:]
   101  	c.Access = args[1]
   102  	// Special case for backwards compatibility.
   103  	if c.Access == "addmodel" {
   104  		c.Access = "add-model"
   105  	}
   106  	if len(c.ModelNames) > 0 {
   107  		if err := permission.ValidateControllerAccess(permission.Access(c.Access)); err == nil {
   108  			return errors.Errorf("You have specified a controller access permission %q.\n"+
   109  				"If you intended to change controller access, do not specify any model names.\n"+
   110  				"See 'juju help grant'.", c.Access)
   111  		}
   112  		return permission.ValidateModelAccess(permission.Access(c.Access))
   113  	}
   114  	if err := permission.ValidateModelAccess(permission.Access(c.Access)); err == nil {
   115  		return errors.Errorf("You have specified a model access permission %q.\n"+
   116  			"If you intended to change model access, you need to specify one or more model names.\n"+
   117  			"See 'juju help grant'.", c.Access)
   118  	}
   119  	return nil
   120  }
   121  
   122  // NewGrantCommand returns a new grant command.
   123  func NewGrantCommand() cmd.Command {
   124  	return modelcmd.WrapController(&grantCommand{})
   125  }
   126  
   127  // grantCommand represents the command to grant a user access to one or more models.
   128  type grantCommand struct {
   129  	accessCommand
   130  	api GrantModelAPI
   131  }
   132  
   133  // Info implements Command.Info.
   134  func (c *grantCommand) Info() *cmd.Info {
   135  	return &cmd.Info{
   136  		Name:    "grant",
   137  		Args:    "<user name> <permission> [<model name> ...]",
   138  		Purpose: usageGrantSummary,
   139  		Doc:     usageGrantDetails,
   140  	}
   141  }
   142  
   143  func (c *grantCommand) getModelAPI() (GrantModelAPI, error) {
   144  	if c.api != nil {
   145  		return c.api, nil
   146  	}
   147  	return c.NewModelManagerAPIClient()
   148  }
   149  
   150  func (c *grantCommand) getControllerAPI() (GrantControllerAPI, error) {
   151  	return c.NewControllerAPIClient()
   152  }
   153  
   154  // GrantModelAPI defines the API functions used by the grant command.
   155  type GrantModelAPI interface {
   156  	Close() error
   157  	GrantModel(user, access string, modelUUIDs ...string) error
   158  }
   159  
   160  // GrantControllerAPI defines the API functions used by the grant command.
   161  type GrantControllerAPI interface {
   162  	Close() error
   163  	GrantController(user, access string) error
   164  }
   165  
   166  // Run implements cmd.Command.
   167  func (c *grantCommand) Run(ctx *cmd.Context) error {
   168  	if len(c.ModelNames) > 0 {
   169  		return c.runForModel()
   170  	}
   171  	return c.runForController()
   172  }
   173  
   174  func (c *grantCommand) runForController() error {
   175  	client, err := c.getControllerAPI()
   176  	if err != nil {
   177  		return err
   178  	}
   179  	defer client.Close()
   180  
   181  	return block.ProcessBlockedError(client.GrantController(c.User, c.Access), block.BlockChange)
   182  }
   183  
   184  func (c *grantCommand) runForModel() error {
   185  	client, err := c.getModelAPI()
   186  	if err != nil {
   187  		return err
   188  	}
   189  	defer client.Close()
   190  
   191  	models, err := c.ModelUUIDs(c.ModelNames)
   192  	if err != nil {
   193  		return err
   194  	}
   195  	return block.ProcessBlockedError(client.GrantModel(c.User, c.Access, models...), block.BlockChange)
   196  }
   197  
   198  // NewRevokeCommand returns a new revoke command.
   199  func NewRevokeCommand() cmd.Command {
   200  	return modelcmd.WrapController(&revokeCommand{})
   201  }
   202  
   203  // revokeCommand revokes a user's access to models.
   204  type revokeCommand struct {
   205  	accessCommand
   206  	api RevokeModelAPI
   207  }
   208  
   209  // Info implements cmd.Command.
   210  func (c *revokeCommand) Info() *cmd.Info {
   211  	return &cmd.Info{
   212  		Name:    "revoke",
   213  		Args:    "<user> <permission> [<model name> ...]",
   214  		Purpose: usageRevokeSummary,
   215  		Doc:     usageRevokeDetails,
   216  	}
   217  }
   218  
   219  func (c *revokeCommand) getModelAPI() (RevokeModelAPI, error) {
   220  	if c.api != nil {
   221  		return c.api, nil
   222  	}
   223  	return c.NewModelManagerAPIClient()
   224  }
   225  
   226  func (c *revokeCommand) getControllerAPI() (RevokeControllerAPI, error) {
   227  	return c.NewControllerAPIClient()
   228  }
   229  
   230  // RevokeModelAPI defines the API functions used by the revoke command.
   231  type RevokeModelAPI interface {
   232  	Close() error
   233  	RevokeModel(user, access string, modelUUIDs ...string) error
   234  }
   235  
   236  // RevokeControllerAPI defines the API functions used by the revoke command.
   237  type RevokeControllerAPI interface {
   238  	Close() error
   239  	RevokeController(user, access string) error
   240  }
   241  
   242  // Run implements cmd.Command.
   243  func (c *revokeCommand) Run(ctx *cmd.Context) error {
   244  	if len(c.ModelNames) > 0 {
   245  		return c.runForModel()
   246  	}
   247  	return c.runForController()
   248  }
   249  
   250  func (c *revokeCommand) runForController() error {
   251  	client, err := c.getControllerAPI()
   252  	if err != nil {
   253  		return err
   254  	}
   255  	defer client.Close()
   256  
   257  	return block.ProcessBlockedError(client.RevokeController(c.User, c.Access), block.BlockChange)
   258  }
   259  
   260  func (c *revokeCommand) runForModel() error {
   261  	client, err := c.getModelAPI()
   262  	if err != nil {
   263  		return err
   264  	}
   265  	defer client.Close()
   266  
   267  	models, err := c.ModelUUIDs(c.ModelNames)
   268  	if err != nil {
   269  		return err
   270  	}
   271  	return block.ProcessBlockedError(client.RevokeModel(c.User, c.Access, models...), block.BlockChange)
   272  }