github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/budget/budget.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package budget defines the command used to update budgets. 5 package budget 6 7 import ( 8 "fmt" 9 "strconv" 10 "strings" 11 12 "github.com/juju/cmd" 13 "github.com/juju/errors" 14 "github.com/juju/gnuflag" 15 api "github.com/juju/romulus/api/budget" 16 "github.com/juju/utils" 17 "gopkg.in/macaroon-bakery.v2-unstable/httpbakery" 18 19 jujucmd "github.com/juju/juju/cmd" 20 rcmd "github.com/juju/juju/cmd/juju/romulus" 21 "github.com/juju/juju/cmd/modelcmd" 22 ) 23 24 type budgetCommand struct { 25 modelcmd.ModelCommandBase 26 modelUUID string 27 api apiClient 28 Wallet string 29 Limit string 30 } 31 32 // NewBudgetCommand returns a new budgetCommand. 33 func NewBudgetCommand() cmd.Command { 34 return modelcmd.Wrap(&budgetCommand{}) 35 } 36 37 func (c *budgetCommand) newBudgetAPIClient(apiRoot string, bakery *httpbakery.Client) (apiClient, error) { 38 if c.api != nil { 39 return c.api, nil 40 } 41 var err error 42 c.api, err = api.NewClient(api.APIRoot(apiRoot), api.HTTPClient(bakery)) 43 if err != nil { 44 return nil, errors.Trace(err) 45 } 46 return c.api, nil 47 } 48 49 type apiClient interface { 50 UpdateBudget(string, string, string) (string, error) 51 } 52 53 const doc = ` 54 Updates an existing budget for a model. 55 56 Examples: 57 # Sets the budget for the current model to 10. 58 juju budget 10 59 # Moves the budget for the current model to wallet 'personal' and sets the limit to 10. 60 juju budget personal:10 61 ` 62 63 // Info implements cmd.Command.Info. 64 func (c *budgetCommand) Info() *cmd.Info { 65 return jujucmd.Info(&cmd.Info{ 66 Name: "budget", 67 Args: "[<wallet>:]<limit>", 68 Purpose: "Update a budget.", 69 Doc: doc, 70 }) 71 } 72 73 func (c *budgetCommand) SetFlags(f *gnuflag.FlagSet) { 74 f.StringVar(&c.modelUUID, "model-uuid", "", "Model uuid to set budget for.") 75 c.ModelCommandBase.SetFlags(f) 76 } 77 78 func budgetDefinition(input string) (wallet, limit string, err error) { 79 tokens := strings.Split(input, ":") 80 switch len(tokens) { 81 case 1: 82 return "", tokens[0], nil 83 case 2: 84 return tokens[0], tokens[1], nil 85 default: 86 return "", "", errors.Errorf("invalid budget definition: %v", input) 87 } 88 } 89 90 // Init implements cmd.Command.Init. 91 func (c *budgetCommand) Init(args []string) error { 92 if len(args) < 1 { 93 return errors.New("value required") 94 } 95 96 wallet, limit, err := budgetDefinition(args[0]) 97 if err != nil { 98 return errors.Trace(err) 99 } 100 if _, err := strconv.ParseInt(limit, 10, 32); err != nil { 101 return errors.New("budget limit needs to be a whole number") 102 } 103 c.Wallet = wallet 104 c.Limit = limit 105 if c.modelUUID != "" { 106 if !utils.IsValidUUIDString(c.modelUUID) { 107 return errors.NotValidf("provided model UUID %q", c.modelUUID) 108 } 109 } 110 return c.ModelCommandBase.Init(args[1:]) 111 } 112 113 func (c *budgetCommand) getModelUUID() (string, error) { 114 if c.modelUUID != "" { 115 return c.modelUUID, nil 116 } 117 _, details, err := c.ModelCommandBase.ModelDetails() 118 if err != nil { 119 return "", errors.Trace(err) 120 } 121 return details.ModelUUID, nil 122 } 123 124 // Run implements cmd.Command.Run and contains most of the setwallet logic. 125 func (c *budgetCommand) Run(ctx *cmd.Context) error { 126 modelUUID, err := c.getModelUUID() 127 if err != nil { 128 return errors.Annotate(err, "failed to get model uuid") 129 } 130 client, err := c.BakeryClient() 131 if err != nil { 132 return errors.Annotate(err, "failed to create an http client") 133 } 134 apiRoot, err := rcmd.GetMeteringURLForModelCmd(&c.ModelCommandBase) 135 if err != nil { 136 return errors.Trace(err) 137 } 138 api, err := c.newBudgetAPIClient(apiRoot, client) 139 if err != nil { 140 return errors.Annotate(err, "failed to create an api client") 141 } 142 resp, err := api.UpdateBudget(modelUUID, c.Wallet, c.Limit) 143 if err != nil { 144 return errors.Annotate(err, "failed to update the budget") 145 } 146 fmt.Fprintln(ctx.Stdout, resp) 147 return nil 148 }