github.com/quite/nomad@v0.8.6/command/job_revert.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/nomad/api/contexts" 8 "github.com/posener/complete" 9 ) 10 11 type JobRevertCommand struct { 12 Meta 13 } 14 15 func (c *JobRevertCommand) Help() string { 16 helpText := ` 17 Usage: nomad job revert [options] <job> <version> 18 19 Revert is used to revert a job to a prior version of the job. The available 20 versions to revert to can be found using "nomad job history" command. 21 22 General Options: 23 24 ` + generalOptionsUsage() + ` 25 26 Revert Options: 27 28 -detach 29 Return immediately instead of entering monitor mode. After job revert, 30 the evaluation ID will be printed to the screen, which can be used to 31 examine the evaluation using the eval-status command. 32 33 -verbose 34 Display full information. 35 ` 36 return strings.TrimSpace(helpText) 37 } 38 39 func (c *JobRevertCommand) Synopsis() string { 40 return "Revert to a prior version of the job" 41 } 42 43 func (c *JobRevertCommand) AutocompleteFlags() complete.Flags { 44 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 45 complete.Flags{ 46 "-detach": complete.PredictNothing, 47 "-verbose": complete.PredictNothing, 48 }) 49 } 50 51 func (c *JobRevertCommand) AutocompleteArgs() complete.Predictor { 52 return complete.PredictFunc(func(a complete.Args) []string { 53 client, err := c.Meta.Client() 54 if err != nil { 55 return nil 56 } 57 58 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Jobs, nil) 59 if err != nil { 60 return []string{} 61 } 62 return resp.Matches[contexts.Jobs] 63 }) 64 } 65 66 func (c *JobRevertCommand) Name() string { return "job revert" } 67 68 func (c *JobRevertCommand) Run(args []string) int { 69 var detach, verbose bool 70 71 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 72 flags.Usage = func() { c.Ui.Output(c.Help()) } 73 flags.BoolVar(&detach, "detach", false, "") 74 flags.BoolVar(&verbose, "verbose", false, "") 75 76 if err := flags.Parse(args); err != nil { 77 return 1 78 } 79 80 // Truncate the id unless full length is requested 81 length := shortId 82 if verbose { 83 length = fullId 84 } 85 86 // Check that we got two args 87 args = flags.Args() 88 if l := len(args); l != 2 { 89 c.Ui.Error("This command takes two arguments: <job> <version>") 90 c.Ui.Error(commandErrorText(c)) 91 return 1 92 } 93 94 // Get the HTTP client 95 client, err := c.Meta.Client() 96 if err != nil { 97 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 98 return 1 99 } 100 101 jobID := args[0] 102 revertVersion, ok, err := parseVersion(args[1]) 103 if !ok { 104 c.Ui.Error("The job version to revert to must be specified using the -job-version flag") 105 return 1 106 } 107 if err != nil { 108 c.Ui.Error(fmt.Sprintf("Failed to parse job-version flag: %v", err)) 109 return 1 110 } 111 112 // Check if the job exists 113 jobs, _, err := client.Jobs().PrefixList(jobID) 114 if err != nil { 115 c.Ui.Error(fmt.Sprintf("Error listing jobs: %s", err)) 116 return 1 117 } 118 if len(jobs) == 0 { 119 c.Ui.Error(fmt.Sprintf("No job(s) with prefix or id %q found", jobID)) 120 return 1 121 } 122 if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID { 123 c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs))) 124 return 1 125 } 126 127 // Prefix lookup matched a single job 128 resp, _, err := client.Jobs().Revert(jobs[0].ID, revertVersion, nil, nil) 129 if err != nil { 130 c.Ui.Error(fmt.Sprintf("Error retrieving job versions: %s", err)) 131 return 1 132 } 133 134 // Nothing to do 135 evalCreated := resp.EvalID != "" 136 if detach || !evalCreated { 137 return 0 138 } 139 140 mon := newMonitor(c.Ui, client, length) 141 return mon.monitor(resp.EvalID, false) 142 }