github.com/nir0s/nomad@v0.8.7-rc1/command/status.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/nomad/api/contexts" 8 "github.com/mitchellh/cli" 9 "github.com/posener/complete" 10 ) 11 12 type StatusCommand struct { 13 Meta 14 } 15 16 func (s *StatusCommand) Help() string { 17 helpText := ` 18 Usage: nomad status [options] <identifier> 19 20 Display the status output for any given resource. The command will 21 detect the type of resource being queried and display the appropriate 22 status output. 23 24 General Options: 25 26 ` + generalOptionsUsage() 27 28 return strings.TrimSpace(helpText) 29 } 30 31 func (c *StatusCommand) Synopsis() string { 32 return "Display the status output for a resource" 33 } 34 35 func (c *StatusCommand) AutocompleteFlags() complete.Flags { 36 return c.Meta.AutocompleteFlags(FlagSetClient) 37 } 38 39 func (c *StatusCommand) AutocompleteArgs() complete.Predictor { 40 return complete.PredictFunc(func(a complete.Args) []string { 41 client, err := c.Meta.Client() 42 if err != nil { 43 return nil 44 } 45 46 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.All, nil) 47 if err != nil { 48 return []string{} 49 } 50 51 final := make([]string, 0) 52 53 for _, matches := range resp.Matches { 54 if len(matches) == 0 { 55 continue 56 } 57 58 final = append(final, matches...) 59 } 60 61 return final 62 }) 63 } 64 65 func (c *StatusCommand) Run(args []string) int { 66 flags := c.Meta.FlagSet("status", FlagSetClient) 67 flags.Usage = func() { c.Ui.Output(c.Help()) } 68 69 if err := flags.Parse(args); err != nil { 70 c.Ui.Error(fmt.Sprintf("Error parsing arguments: %q", err)) 71 return 1 72 } 73 74 // Store the original arguments so we can pass them to the routed command 75 argsCopy := args 76 77 // Check that we got exactly one evaluation ID 78 args = flags.Args() 79 80 // Get the HTTP client 81 client, err := c.Meta.Client() 82 if err != nil { 83 c.Ui.Error(fmt.Sprintf("Error initializing client: %q", err)) 84 return 1 85 } 86 87 // If no identifier is provided, default to listing jobs 88 if len(args) == 0 { 89 cmd := &JobStatusCommand{Meta: c.Meta} 90 return cmd.Run(argsCopy) 91 } 92 93 id := args[len(args)-1] 94 95 // Query for the context associated with the id 96 res, _, err := client.Search().PrefixSearch(id, contexts.All, nil) 97 if err != nil { 98 c.Ui.Error(fmt.Sprintf("Error querying search with id: %q", err)) 99 return 1 100 } 101 102 if res.Matches == nil { 103 c.Ui.Error(fmt.Sprintf("No matches returned for query: %q", err)) 104 return 1 105 } 106 107 var match contexts.Context 108 exactMatches := 0 109 for ctx, vers := range res.Matches { 110 if len(vers) > 0 && vers[0] == id { 111 match = ctx 112 exactMatches++ 113 } 114 } 115 116 if exactMatches > 1 { 117 c.logMultiMatchError(id, res.Matches) 118 return 1 119 } else if exactMatches == 0 { 120 matchCount := 0 121 for ctx, vers := range res.Matches { 122 l := len(vers) 123 if l == 1 { 124 match = ctx 125 matchCount++ 126 } 127 128 // Only a single result should return, as this is a match against a full id 129 if matchCount > 1 || l > 1 { 130 c.logMultiMatchError(id, res.Matches) 131 return 1 132 } 133 } 134 } 135 136 var cmd cli.Command 137 switch match { 138 case contexts.Evals: 139 cmd = &EvalStatusCommand{Meta: c.Meta} 140 case contexts.Nodes: 141 cmd = &NodeStatusCommand{Meta: c.Meta} 142 case contexts.Allocs: 143 cmd = &AllocStatusCommand{Meta: c.Meta} 144 case contexts.Jobs: 145 cmd = &JobStatusCommand{Meta: c.Meta} 146 case contexts.Deployments: 147 cmd = &DeploymentStatusCommand{Meta: c.Meta} 148 case contexts.Namespaces: 149 cmd = &NamespaceStatusCommand{Meta: c.Meta} 150 case contexts.Quotas: 151 cmd = &QuotaStatusCommand{Meta: c.Meta} 152 default: 153 c.Ui.Error(fmt.Sprintf("Unable to resolve ID: %q", id)) 154 return 1 155 } 156 157 return cmd.Run(argsCopy) 158 } 159 160 // logMultiMatchError is used to log an error message when multiple matches are 161 // found. The error message logged displays the matched IDs per context. 162 func (c *StatusCommand) logMultiMatchError(id string, matches map[contexts.Context][]string) { 163 c.Ui.Error(fmt.Sprintf("Multiple matches found for id %q", id)) 164 for ctx, vers := range matches { 165 if len(vers) == 0 { 166 continue 167 } 168 169 c.Ui.Error(fmt.Sprintf("\n%s:", strings.Title(string(ctx)))) 170 c.Ui.Error(fmt.Sprintf("%s", strings.Join(vers, ", "))) 171 } 172 }