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