github.com/hernad/nomad@v1.6.112/command/job_eval.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/hernad/nomad/api" 11 "github.com/hernad/nomad/api/contexts" 12 "github.com/posener/complete" 13 ) 14 15 type JobEvalCommand struct { 16 Meta 17 forceRescheduling bool 18 } 19 20 func (c *JobEvalCommand) Help() string { 21 helpText := ` 22 Usage: nomad job eval [options] <job_id> 23 24 Force an evaluation of the provided job ID. Forcing an evaluation will 25 trigger the scheduler to re-evaluate the job. The force flags allow 26 operators to force the scheduler to create new allocations under certain 27 scenarios. 28 29 When ACLs are enabled, this command requires a token with the 'submit-job' 30 capability for the job's namespace. The 'list-jobs' capability is required to 31 run the command with a job prefix instead of the exact job ID. The 'read-job' 32 capability is required to monitor the resulting evaluation when -detach is 33 not used. 34 35 General Options: 36 37 ` + generalOptionsUsage(usageOptsDefault) + ` 38 39 Eval Options: 40 41 -force-reschedule 42 Force reschedule failed allocations even if they are not currently 43 eligible for rescheduling. 44 45 -detach 46 Return immediately instead of entering monitor mode. The ID 47 of the evaluation created will be printed to the screen, which can be 48 used to examine the evaluation using the eval-status command. 49 50 -verbose 51 Display full information. 52 ` 53 return strings.TrimSpace(helpText) 54 } 55 56 func (c *JobEvalCommand) Synopsis() string { 57 return "Force an evaluation for the job" 58 } 59 60 func (c *JobEvalCommand) AutocompleteFlags() complete.Flags { 61 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 62 complete.Flags{ 63 "-force-reschedule": complete.PredictNothing, 64 "-detach": complete.PredictNothing, 65 "-verbose": complete.PredictNothing, 66 }) 67 } 68 69 func (c *JobEvalCommand) AutocompleteArgs() complete.Predictor { 70 return complete.PredictFunc(func(a complete.Args) []string { 71 client, err := c.Meta.Client() 72 if err != nil { 73 return nil 74 } 75 76 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Jobs, nil) 77 if err != nil { 78 return []string{} 79 } 80 return resp.Matches[contexts.Jobs] 81 }) 82 } 83 84 func (c *JobEvalCommand) Name() string { return "job eval" } 85 86 func (c *JobEvalCommand) Run(args []string) int { 87 var detach, verbose bool 88 89 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 90 flags.Usage = func() { c.Ui.Output(c.Help()) } 91 flags.BoolVar(&c.forceRescheduling, "force-reschedule", false, "") 92 flags.BoolVar(&detach, "detach", false, "") 93 flags.BoolVar(&verbose, "verbose", false, "") 94 95 if err := flags.Parse(args); err != nil { 96 return 1 97 } 98 99 // Check that we either got no jobs or exactly one. 100 args = flags.Args() 101 if len(args) != 1 { 102 c.Ui.Error("This command takes one argument: <job>") 103 c.Ui.Error(commandErrorText(c)) 104 return 1 105 } 106 107 // Get the HTTP client 108 client, err := c.Meta.Client() 109 if err != nil { 110 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 111 return 1 112 } 113 114 // Truncate the id unless full length is requested 115 length := shortId 116 if verbose { 117 length = fullId 118 } 119 120 // Check if the job exists 121 jobIDPrefix := strings.TrimSpace(args[0]) 122 jobID, namespace, err := c.JobIDByPrefix(client, jobIDPrefix, nil) 123 if err != nil { 124 c.Ui.Error(err.Error()) 125 return 1 126 } 127 128 // Call eval endpoint 129 opts := api.EvalOptions{ 130 ForceReschedule: c.forceRescheduling, 131 } 132 w := &api.WriteOptions{ 133 Namespace: namespace, 134 } 135 evalId, _, err := client.Jobs().EvaluateWithOpts(jobID, opts, w) 136 if err != nil { 137 c.Ui.Error(fmt.Sprintf("Error evaluating job: %s", err)) 138 return 1 139 } 140 141 if detach { 142 c.Ui.Output(fmt.Sprintf("Created eval ID: %q ", limit(evalId, length))) 143 return 0 144 } 145 146 mon := newMonitor(c.Ui, client, length) 147 return mon.monitor(evalId) 148 }