github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/romulus/allocate/allocate.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package allocate 5 6 import ( 7 "fmt" 8 "regexp" 9 "strings" 10 11 "github.com/juju/cmd" 12 "github.com/juju/errors" 13 "github.com/juju/gnuflag" 14 "github.com/juju/juju/cmd/modelcmd" 15 "github.com/juju/utils" 16 "gopkg.in/macaroon-bakery.v1/httpbakery" 17 18 api "github.com/juju/romulus/api/budget" 19 ) 20 21 var budgetWithLimitRe = regexp.MustCompile(`^[a-zA-Z0-9\-]+:[0-9]+$`) 22 23 type allocateCommand struct { 24 modelcmd.ModelCommandBase 25 api apiClient 26 Budget string 27 ModelUUID string 28 Services []string 29 Limit string 30 } 31 32 // NewAllocateCommand returns a new allocateCommand 33 func NewAllocateCommand() modelcmd.ModelCommand { 34 return &allocateCommand{} 35 } 36 37 const doc = ` 38 Allocate budget for the specified applications, replacing any prior allocations 39 made for the specified applications. 40 41 Examples: 42 # Assigns application "db" to an allocation on budget "somebudget" with 43 # the limit "42". 44 juju allocate somebudget:42 db 45 46 # Application names assume the current selected model, unless otherwise 47 # specified with: 48 juju allocate -m [<controller name:]<model name> ... 49 50 # Models may also be referenced by UUID when necessary: 51 juju allocate --model-uuid <uuid> ... 52 ` 53 54 // SetFlags implements cmd.Command.SetFlags. 55 func (c *allocateCommand) SetFlags(f *gnuflag.FlagSet) { 56 c.ModelCommandBase.SetFlags(f) 57 f.StringVar(&c.ModelUUID, "model-uuid", "", "Model UUID of allocation") 58 } 59 60 // Info implements cmd.Command.Info. 61 func (c *allocateCommand) Info() *cmd.Info { 62 return &cmd.Info{ 63 Name: "allocate", 64 Args: "<budget>:<value> <application> [<application2> ...]", 65 Purpose: "Allocate budget to applications.", 66 Doc: doc, 67 } 68 } 69 70 // Init implements cmd.Command.Init. 71 func (c *allocateCommand) Init(args []string) error { 72 if len(args) < 2 { 73 return errors.New("budget and application name required") 74 } 75 budgetWithLimit := args[0] 76 var err error 77 c.Budget, c.Limit, err = parseBudgetWithLimit(budgetWithLimit) 78 if err != nil { 79 return errors.Annotate(err, `expected args in the form "budget:limit [application ...]"`) 80 } 81 if c.ModelUUID == "" { 82 c.ModelUUID, err = c.modelUUID() 83 if err != nil { 84 return err 85 } 86 } else { 87 if !utils.IsValidUUIDString(c.ModelUUID) { 88 return errors.NotValidf("model UUID %q", c.ModelUUID) 89 } 90 } 91 92 c.Services = args[1:] 93 return nil 94 } 95 96 // Run implements cmd.Command.Run and has most of the logic for the run command. 97 func (c *allocateCommand) Run(ctx *cmd.Context) error { 98 client, err := c.BakeryClient() 99 if err != nil { 100 return errors.Annotate(err, "failed to create an http client") 101 } 102 api, err := c.newAPIClient(client) 103 if err != nil { 104 return errors.Annotate(err, "failed to create an api client") 105 } 106 resp, err := api.CreateAllocation(c.Budget, c.Limit, c.ModelUUID, c.Services) 107 if err != nil { 108 return errors.Annotate(err, "failed to create allocation") 109 } 110 fmt.Fprintln(ctx.Stdout, resp) 111 return nil 112 } 113 114 func (c *allocateCommand) modelUUID() (string, error) { 115 model, err := c.ClientStore().ModelByName(c.ControllerName(), c.ModelName()) 116 if err != nil { 117 return "", errors.Trace(err) 118 } 119 return model.ModelUUID, nil 120 } 121 122 func parseBudgetWithLimit(bl string) (string, string, error) { 123 if !budgetWithLimitRe.MatchString(bl) { 124 return "", "", errors.New("invalid budget specification, expecting <budget>:<limit>") 125 } 126 parts := strings.Split(bl, ":") 127 return parts[0], parts[1], nil 128 } 129 130 func (c *allocateCommand) newAPIClient(bakery *httpbakery.Client) (apiClient, error) { 131 if c.api != nil { 132 return c.api, nil 133 } 134 c.api = api.NewClient(bakery) 135 return c.api, nil 136 } 137 138 type apiClient interface { 139 CreateAllocation(string, string, string, []string) (string, error) 140 }