github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/eval_list.go (about)

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