github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/romulus/listbudgets/list-budgets.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package listbudgets 5 6 import ( 7 "fmt" 8 "io" 9 "sort" 10 11 "github.com/gosuri/uitable" 12 "github.com/juju/cmd" 13 "github.com/juju/errors" 14 "github.com/juju/gnuflag" 15 "github.com/juju/juju/cmd/modelcmd" 16 "gopkg.in/macaroon-bakery.v1/httpbakery" 17 18 api "github.com/juju/romulus/api/budget" 19 wireformat "github.com/juju/romulus/wireformat/budget" 20 ) 21 22 // NewListBudgetsCommand returns a new command that is used 23 // to list budgets a user has access to. 24 func NewListBudgetsCommand() modelcmd.CommandBase { 25 return &listBudgetsCommand{} 26 } 27 28 type listBudgetsCommand struct { 29 modelcmd.JujuCommandBase 30 31 out cmd.Output 32 } 33 34 const listBudgetsDoc = ` 35 List the available budgets. 36 37 Examples: 38 juju budgets 39 ` 40 41 // Info implements cmd.Command.Info. 42 func (c *listBudgetsCommand) Info() *cmd.Info { 43 return &cmd.Info{ 44 Name: "budgets", 45 Purpose: "List budgets.", 46 Doc: listBudgetsDoc, 47 Aliases: []string{"list-budgets"}, 48 } 49 } 50 51 // SetFlags implements cmd.Command.SetFlags. 52 func (c *listBudgetsCommand) SetFlags(f *gnuflag.FlagSet) { 53 c.JujuCommandBase.SetFlags(f) 54 c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{ 55 "tabular": formatTabular, 56 "json": cmd.FormatJson, 57 }) 58 } 59 60 func (c *listBudgetsCommand) Run(ctx *cmd.Context) error { 61 client, err := c.BakeryClient() 62 if err != nil { 63 return errors.Annotate(err, "failed to create an http client") 64 } 65 api, err := newAPIClient(client) 66 if err != nil { 67 return errors.Annotate(err, "failed to create an api client") 68 } 69 budgets, err := api.ListBudgets() 70 if err != nil { 71 return errors.Annotate(err, "failed to retrieve budgets") 72 } 73 if budgets == nil { 74 return errors.New("no budget information available") 75 } 76 err = c.out.Write(ctx, budgets) 77 if err != nil { 78 return errors.Trace(err) 79 } 80 return nil 81 } 82 83 // formatTabular returns a tabular view of available budgets. 84 func formatTabular(writer io.Writer, value interface{}) error { 85 b, ok := value.(*wireformat.ListBudgetsResponse) 86 if !ok { 87 return errors.Errorf("expected value of type %T, got %T", b, value) 88 } 89 sort.Sort(b.Budgets) 90 91 table := uitable.New() 92 table.MaxColWidth = 50 93 table.Wrap = true 94 for _, col := range []int{1, 2, 3, 4} { 95 table.RightAlign(col) 96 } 97 98 table.AddRow("BUDGET", "MONTHLY", "ALLOCATED", "AVAILABLE", "SPENT") 99 for _, budgetEntry := range b.Budgets { 100 table.AddRow(budgetEntry.Budget, budgetEntry.Limit, budgetEntry.Allocated, budgetEntry.Available, budgetEntry.Consumed) 101 } 102 table.AddRow("TOTAL", b.Total.Limit, b.Total.Allocated, b.Total.Available, b.Total.Consumed) 103 table.AddRow("", "", "", "", "") 104 table.AddRow("Credit limit:", b.Credit, "", "", "") 105 fmt.Fprint(writer, table) 106 return nil 107 } 108 109 var newAPIClient = newAPIClientImpl 110 111 func newAPIClientImpl(c *httpbakery.Client) (apiClient, error) { 112 client := api.NewClient(c) 113 return client, nil 114 } 115 116 type apiClient interface { 117 // ListBudgets returns a list of budgets a user has access to. 118 ListBudgets() (*wireformat.ListBudgetsResponse, error) 119 }