github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/action/status.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 "github.com/juju/cmd" 8 errors "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/cmd/modelcmd" 14 "github.com/juju/juju/cmd/output" 15 ) 16 17 func NewStatusCommand() cmd.Command { 18 return modelcmd.Wrap(&statusCommand{}) 19 } 20 21 // statusCommand shows the status of an Action by ID. 22 type statusCommand struct { 23 ActionCommandBase 24 out cmd.Output 25 requestedId string 26 name string 27 } 28 29 const statusDoc = ` 30 Show the status of Actions matching given ID, partial ID prefix, or all Actions if no ID is supplied. 31 If --name <name> is provided the search will be done by name rather than by ID. 32 ` 33 34 // Set up the output. 35 func (c *statusCommand) SetFlags(f *gnuflag.FlagSet) { 36 c.ActionCommandBase.SetFlags(f) 37 c.out.AddFlags(f, "yaml", output.DefaultFormatters) 38 f.StringVar(&c.name, "name", "", "Action name") 39 } 40 41 func (c *statusCommand) Info() *cmd.Info { 42 return &cmd.Info{ 43 Name: "show-action-status", 44 Args: "[<action ID>|<action ID prefix>]", 45 Purpose: "Show results of all actions filtered by optional ID prefix.", 46 Doc: statusDoc, 47 } 48 } 49 50 func (c *statusCommand) Init(args []string) error { 51 switch len(args) { 52 case 0: 53 c.requestedId = "" 54 return nil 55 case 1: 56 c.requestedId = args[0] 57 return nil 58 default: 59 return cmd.CheckEmpty(args[1:]) 60 } 61 } 62 63 func (c *statusCommand) Run(ctx *cmd.Context) error { 64 api, err := c.NewActionAPIClient() 65 if err != nil { 66 return err 67 } 68 defer api.Close() 69 70 if c.name != "" { 71 actions, err := GetActionsByName(api, c.name) 72 if err != nil { 73 return errors.Trace(err) 74 } 75 return c.out.Write(ctx, resultsToMap(actions)) 76 } 77 78 actionTags, err := getActionTagsByPrefix(api, c.requestedId) 79 if err != nil { 80 return err 81 } 82 83 if len(actionTags) < 1 { 84 if len(c.requestedId) == 0 { 85 return errors.Errorf("no actions found") 86 } else { 87 return errors.Errorf("no actions found matching prefix %q", c.requestedId) 88 } 89 } 90 91 entities := []params.Entity{} 92 for _, tag := range actionTags { 93 entities = append(entities, params.Entity{tag.String()}) 94 } 95 96 actions, err := api.Actions(params.Entities{Entities: entities}) 97 if err != nil { 98 return err 99 } 100 101 if len(actions.Results) < 1 { 102 return errors.Errorf("identifier %q matched action(s) %v, but found no results", c.requestedId, actionTags) 103 } 104 105 return c.out.Write(ctx, resultsToMap(actions.Results)) 106 } 107 108 // resultsToMap is a helper function that takes in a []params.ActionResult 109 // and returns a map[string]interface{} ready to be served to the 110 // formatter for printing. 111 func resultsToMap(results []params.ActionResult) map[string]interface{} { 112 items := []map[string]interface{}{} 113 for _, item := range results { 114 items = append(items, resultToMap(item)) 115 } 116 return map[string]interface{}{"actions": items} 117 } 118 119 func resultToMap(result params.ActionResult) map[string]interface{} { 120 item := map[string]interface{}{} 121 if result.Error != nil { 122 item["error"] = result.Error.Error() 123 } 124 if result.Action != nil { 125 atag, err := names.ParseActionTag(result.Action.Tag) 126 if err != nil { 127 item["id"] = result.Action.Tag 128 } else { 129 item["id"] = atag.Id() 130 } 131 132 rtag, err := names.ParseUnitTag(result.Action.Receiver) 133 if err != nil { 134 item["unit"] = result.Action.Receiver 135 } else { 136 item["unit"] = rtag.Id() 137 } 138 139 } 140 item["status"] = result.Status 141 return item 142 } 143 144 // GetActionsByName takes an action APIClient and a name and returns a list of 145 // ActionResults. 146 func GetActionsByName(api APIClient, name string) ([]params.ActionResult, error) { 147 nothing := []params.ActionResult{} 148 results, err := api.FindActionsByNames(params.FindActionsByNames{ActionNames: []string{name}}) 149 if err != nil { 150 return nothing, errors.Trace(err) 151 } 152 if len(results.Actions) != 1 { 153 return nothing, errors.Errorf("expected one result got %d", len(results.Actions)) 154 } 155 result := results.Actions[0] 156 if result.Error != nil { 157 return nothing, result.Error 158 } 159 if len(result.Actions) < 1 { 160 return nothing, errors.Errorf("no actions were found for name %s", name) 161 } 162 return result.Actions, nil 163 164 }