github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/action/list.go (about) 1 // Copyright 2014, 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package action 5 6 import ( 7 "fmt" 8 "io" 9 "strings" 10 11 "github.com/juju/cmd" 12 errors "github.com/juju/errors" 13 "github.com/juju/gnuflag" 14 "github.com/juju/utils" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/apiserver/params" 18 "github.com/juju/juju/cmd/modelcmd" 19 "github.com/juju/juju/cmd/output" 20 ) 21 22 func NewListCommand() cmd.Command { 23 return modelcmd.Wrap(&listCommand{}) 24 } 25 26 // listCommand lists actions defined by the charm of a given service. 27 type listCommand struct { 28 ActionCommandBase 29 applicationTag names.ApplicationTag 30 fullSchema bool 31 out cmd.Output 32 } 33 34 const listDoc = ` 35 List the actions available to run on the target application, with a short 36 description. To show the full schema for the actions, use --schema. 37 38 For more information, see also the 'run-action' command, which executes actions. 39 ` 40 41 // Set up the output. 42 func (c *listCommand) SetFlags(f *gnuflag.FlagSet) { 43 c.ActionCommandBase.SetFlags(f) 44 c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{ 45 "yaml": cmd.FormatYaml, 46 "json": cmd.FormatJson, 47 "tabular": c.printTabular, 48 }) 49 f.BoolVar(&c.fullSchema, "schema", false, "Display the full action schema") 50 } 51 52 func (c *listCommand) Info() *cmd.Info { 53 return &cmd.Info{ 54 Name: "actions", 55 Args: "<application name>", 56 Purpose: "List actions defined for a service.", 57 Doc: listDoc, 58 Aliases: []string{"list-actions"}, 59 } 60 } 61 62 // Init validates the service name and any other options. 63 func (c *listCommand) Init(args []string) error { 64 if c.out.Name() == "tabular" && c.fullSchema { 65 return errors.New("full schema not compatible with tabular output") 66 } 67 switch len(args) { 68 case 0: 69 return errors.New("no application name specified") 70 case 1: 71 svcName := args[0] 72 if !names.IsValidApplication(svcName) { 73 return errors.Errorf("invalid application name %q", svcName) 74 } 75 c.applicationTag = names.NewApplicationTag(svcName) 76 return nil 77 default: 78 return cmd.CheckEmpty(args[1:]) 79 } 80 } 81 82 // Run grabs the Actions spec from the api. It then sets up a sensible 83 // output format for the map. 84 func (c *listCommand) Run(ctx *cmd.Context) error { 85 api, err := c.NewActionAPIClient() 86 if err != nil { 87 return err 88 } 89 defer api.Close() 90 91 actions, err := api.ApplicationCharmActions(params.Entity{c.applicationTag.String()}) 92 if err != nil { 93 return err 94 } 95 96 if c.fullSchema { 97 verboseSpecs := make(map[string]interface{}) 98 for k, v := range actions { 99 verboseSpecs[k] = v.Params 100 } 101 102 return c.out.Write(ctx, verboseSpecs) 103 } 104 105 shortOutput := make(map[string]string) 106 var sortedNames []string 107 for name, action := range actions { 108 shortOutput[name] = action.Description 109 if shortOutput[name] == "" { 110 shortOutput[name] = "No description" 111 } 112 sortedNames = append(sortedNames, name) 113 } 114 utils.SortStringsNaturally(sortedNames) 115 116 var output interface{} 117 switch c.out.Name() { 118 case "yaml", "json": 119 output = shortOutput 120 default: 121 if len(sortedNames) == 0 { 122 ctx.Infof("No actions defined for %s.", c.applicationTag.Id()) 123 return nil 124 } 125 var list []listOutput 126 for _, name := range sortedNames { 127 list = append(list, listOutput{name, shortOutput[name]}) 128 } 129 output = list 130 } 131 132 return c.out.Write(ctx, output) 133 } 134 135 type listOutput struct { 136 action string 137 description string 138 } 139 140 // printTabular prints the list of actions in tabular format 141 func (c *listCommand) printTabular(writer io.Writer, value interface{}) error { 142 list, ok := value.([]listOutput) 143 if !ok { 144 return errors.New("unexpected value") 145 } 146 147 tw := output.TabWriter(writer) 148 fmt.Fprintf(tw, "%s\t%s\n", "ACTION", "DESCRIPTION") 149 for _, value := range list { 150 fmt.Fprintf(tw, "%s\t%s\n", value.action, strings.TrimSpace(value.description)) 151 } 152 tw.Flush() 153 return nil 154 }