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