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 }