github.com/hernad/nomad@v1.6.112/command/eval_list.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package command
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/hernad/nomad/api"
    12  	"github.com/hernad/nomad/api/contexts"
    13  	"github.com/posener/complete"
    14  )
    15  
    16  type EvalListCommand struct {
    17  	Meta
    18  }
    19  
    20  func (c *EvalListCommand) Help() string {
    21  	helpText := `
    22  Usage: nomad eval list [options]
    23  
    24    List is used to list the set of evaluations processed by Nomad.
    25  
    26  General Options:
    27  
    28    ` + generalOptionsUsage(usageOptsDefault) + `
    29  
    30  Eval List Options:
    31  
    32    -verbose
    33      Show full information.
    34  
    35    -per-page
    36      How many results to show per page.
    37  
    38    -page-token
    39      Where to start pagination.
    40  
    41    -filter
    42      Specifies an expression used to filter query results.
    43  
    44    -job
    45      Only show evaluations for this job ID.
    46  
    47    -status
    48      Only show evaluations with this status.
    49  
    50    -json
    51      Output the evaluation in its JSON format.
    52  
    53    -t
    54      Format and display evaluation using a Go template.
    55  `
    56  
    57  	return strings.TrimSpace(helpText)
    58  }
    59  
    60  func (c *EvalListCommand) Synopsis() string {
    61  	return "List the set of evaluations processed by Nomad"
    62  }
    63  
    64  func (c *EvalListCommand) AutocompleteFlags() complete.Flags {
    65  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    66  		complete.Flags{
    67  			"-json":       complete.PredictNothing,
    68  			"-t":          complete.PredictAnything,
    69  			"-verbose":    complete.PredictNothing,
    70  			"-filter":     complete.PredictAnything,
    71  			"-job":        complete.PredictAnything,
    72  			"-status":     complete.PredictAnything,
    73  			"-per-page":   complete.PredictAnything,
    74  			"-page-token": complete.PredictAnything,
    75  		})
    76  }
    77  
    78  func (c *EvalListCommand) AutocompleteArgs() complete.Predictor {
    79  	return complete.PredictFunc(func(a complete.Args) []string {
    80  		client, err := c.Meta.Client()
    81  		if err != nil {
    82  			return nil
    83  		}
    84  
    85  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Evals, nil)
    86  		if err != nil {
    87  			return []string{}
    88  		}
    89  		return resp.Matches[contexts.Evals]
    90  	})
    91  }
    92  
    93  func (c *EvalListCommand) Name() string { return "eval list" }
    94  
    95  func (c *EvalListCommand) Run(args []string) int {
    96  	var monitor, verbose, json bool
    97  	var perPage int
    98  	var tmpl, pageToken, filter, filterJobID, filterStatus string
    99  
   100  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
   101  	flags.Usage = func() { c.Ui.Output(c.Help()) }
   102  	flags.BoolVar(&monitor, "monitor", false, "")
   103  	flags.BoolVar(&verbose, "verbose", false, "")
   104  	flags.BoolVar(&json, "json", false, "")
   105  	flags.StringVar(&tmpl, "t", "", "")
   106  	flags.IntVar(&perPage, "per-page", 0, "")
   107  	flags.StringVar(&pageToken, "page-token", "", "")
   108  	flags.StringVar(&filter, "filter", "", "")
   109  	flags.StringVar(&filterJobID, "job", "", "")
   110  	flags.StringVar(&filterStatus, "status", "", "")
   111  
   112  	if err := flags.Parse(args); err != nil {
   113  		return 1
   114  	}
   115  
   116  	// Check that we got no arguments
   117  	args = flags.Args()
   118  	if l := len(args); l != 0 {
   119  		c.Ui.Error("This command takes no arguments")
   120  		c.Ui.Error(commandErrorText(c))
   121  		return 1
   122  	}
   123  
   124  	client, err := c.Meta.Client()
   125  	if err != nil {
   126  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   127  		return 1
   128  	}
   129  
   130  	opts := &api.QueryOptions{
   131  		Filter:    filter,
   132  		PerPage:   int32(perPage),
   133  		NextToken: pageToken,
   134  		Params:    map[string]string{},
   135  	}
   136  	if filterJobID != "" {
   137  		opts.Params["job"] = filterJobID
   138  	}
   139  	if filterStatus != "" {
   140  		opts.Params["status"] = filterStatus
   141  	}
   142  
   143  	evals, qm, err := client.Evaluations().List(opts)
   144  	if err != nil {
   145  		c.Ui.Error(fmt.Sprintf("Error querying evaluations: %v", err))
   146  		return 1
   147  	}
   148  
   149  	// If args not specified but output format is specified, format
   150  	// and output the evaluations data list
   151  	if json || len(tmpl) > 0 {
   152  		out, err := Format(json, tmpl, evals)
   153  		if err != nil {
   154  			c.Ui.Error(err.Error())
   155  			return 1
   156  		}
   157  
   158  		c.Ui.Output(out)
   159  		return 0
   160  	}
   161  
   162  	if len(evals) == 0 {
   163  		c.Ui.Output("No evals found")
   164  		return 0
   165  	}
   166  
   167  	c.Ui.Output(formatEvalList(evals, verbose))
   168  
   169  	if qm.NextToken != "" {
   170  		c.Ui.Output(fmt.Sprintf(`
   171  Results have been paginated. To get the next page run:
   172  
   173  %s -page-token %s`, argsWithoutPageToken(os.Args), qm.NextToken))
   174  	}
   175  
   176  	return 0
   177  }
   178  
   179  // argsWithoutPageToken strips out of the -page-token argument and
   180  // returns the joined string
   181  func argsWithoutPageToken(osArgs []string) string {
   182  	args := []string{}
   183  	i := 0
   184  	for {
   185  		if i >= len(osArgs) {
   186  			break
   187  		}
   188  		arg := osArgs[i]
   189  
   190  		if strings.HasPrefix(arg, "-page-token") {
   191  			if strings.Contains(arg, "=") {
   192  				i += 1
   193  			} else {
   194  				i += 2
   195  			}
   196  			continue
   197  		}
   198  
   199  		args = append(args, arg)
   200  		i++
   201  	}
   202  	return strings.Join(args, " ")
   203  }
   204  
   205  func formatEvalList(evals []*api.Evaluation, verbose bool) string {
   206  	// Truncate IDs unless full length is requested
   207  	length := shortId
   208  	if verbose {
   209  		length = fullId
   210  	}
   211  
   212  	out := make([]string, len(evals)+1)
   213  	out[0] = "ID|Priority|Triggered By|Job ID|Namespace|Node ID|Status|Placement Failures"
   214  	for i, eval := range evals {
   215  		failures, _ := evalFailureStatus(eval)
   216  		out[i+1] = fmt.Sprintf("%s|%d|%s|%s|%s|%s|%s|%s",
   217  			limit(eval.ID, length),
   218  			eval.Priority,
   219  			eval.TriggeredBy,
   220  			eval.JobID,
   221  			eval.Namespace,
   222  			limit(eval.NodeID, length),
   223  			eval.Status,
   224  			failures,
   225  		)
   226  	}
   227  
   228  	return formatList(out)
   229  }