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