github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/command/job_periodic_force.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/nomad/api" 8 "github.com/posener/complete" 9 ) 10 11 type JobPeriodicForceCommand struct { 12 Meta 13 } 14 15 func (c *JobPeriodicForceCommand) Help() string { 16 helpText := ` 17 Usage: nomad job periodic force <job id> 18 19 This command is used to force the creation of a new instance of a periodic job. 20 This is used to immediately run a periodic job, even if it violates the job's 21 prohibit_overlap setting. 22 23 General Options: 24 25 ` + generalOptionsUsage() + ` 26 27 Periodic Force Options: 28 29 -detach 30 Return immediately instead of entering monitor mode. After the force, 31 the evaluation ID will be printed to the screen, which can be used to 32 examine the evaluation using the eval-status command. 33 34 -verbose 35 Display full information. 36 ` 37 38 return strings.TrimSpace(helpText) 39 } 40 41 func (c *JobPeriodicForceCommand) Synopsis() string { 42 return "Force the launch of a periodic job" 43 } 44 45 func (c *JobPeriodicForceCommand) AutocompleteFlags() complete.Flags { 46 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 47 complete.Flags{ 48 "-detach": complete.PredictNothing, 49 "-verbose": complete.PredictNothing, 50 }) 51 } 52 53 func (c *JobPeriodicForceCommand) AutocompleteArgs() complete.Predictor { 54 return complete.PredictFunc(func(a complete.Args) []string { 55 client, err := c.Meta.Client() 56 if err != nil { 57 return nil 58 } 59 60 resp, _, err := client.Jobs().PrefixList(a.Last) 61 if err != nil { 62 return []string{} 63 } 64 65 // filter this by periodic jobs 66 matches := make([]string, 0, len(resp)) 67 for _, job := range resp { 68 if job.Periodic { 69 matches = append(matches, job.ID) 70 } 71 } 72 return matches 73 }) 74 } 75 76 func (c *JobPeriodicForceCommand) Name() string { return "job periodic force" } 77 78 func (c *JobPeriodicForceCommand) Run(args []string) int { 79 var detach, verbose bool 80 81 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 82 flags.Usage = func() { c.Ui.Output(c.Help()) } 83 flags.BoolVar(&detach, "detach", false, "") 84 flags.BoolVar(&verbose, "verbose", false, "") 85 86 if err := flags.Parse(args); err != nil { 87 return 1 88 } 89 90 // Check that we got exactly one argument 91 args = flags.Args() 92 if l := len(args); l != 1 { 93 c.Ui.Error("This command takes one argument: <job id>") 94 c.Ui.Error(commandErrorText(c)) 95 return 1 96 } 97 98 // Truncate the id unless full length is requested 99 length := shortId 100 if verbose { 101 length = fullId 102 } 103 104 // Get the HTTP client 105 client, err := c.Meta.Client() 106 if err != nil { 107 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 108 return 1 109 } 110 111 // Check if the job exists 112 jobID := args[0] 113 jobs, _, err := client.Jobs().PrefixList(jobID) 114 if err != nil { 115 c.Ui.Error(fmt.Sprintf("Error forcing periodic job: %s", err)) 116 return 1 117 } 118 // filter non-periodic jobs 119 periodicJobs := make([]*api.JobListStub, 0, len(jobs)) 120 for _, j := range jobs { 121 if j.Periodic { 122 periodicJobs = append(periodicJobs, j) 123 } 124 } 125 if len(periodicJobs) == 0 { 126 c.Ui.Error(fmt.Sprintf("No periodic job(s) with prefix or id %q found", jobID)) 127 return 1 128 } 129 if len(periodicJobs) > 1 { 130 c.Ui.Error(fmt.Sprintf("Prefix matched multiple periodic jobs\n\n%s", createStatusListOutput(periodicJobs))) 131 return 1 132 } 133 jobID = periodicJobs[0].ID 134 135 // force the evaluation 136 evalID, _, err := client.Jobs().PeriodicForce(jobID, nil) 137 if err != nil { 138 c.Ui.Error(fmt.Sprintf("Error forcing periodic job %q: %s", jobID, err)) 139 return 1 140 } 141 142 if detach { 143 c.Ui.Output("Force periodic successful") 144 c.Ui.Output("Evaluation ID: " + evalID) 145 return 0 146 } 147 148 // Detach was not specified, so start monitoring 149 mon := newMonitor(c.Ui, client, length) 150 return mon.monitor(evalID, false) 151 }