job revert

This commit is contained in:
Alex Dadgar 2017-06-29 20:28:52 -07:00
parent 2471b86dec
commit 7719306ef3
5 changed files with 160 additions and 2 deletions

View File

@ -247,7 +247,6 @@ func (j *Jobs) Dispatch(jobID string, meta map[string]string,
return &resp, wm, nil
}
// XXX
// Revert is used to revert the given job to the passed version. If
// enforceVersion is set, the job is only reverted if the current version is at
// the passed version.

120
command/job_revert.go Normal file
View File

@ -0,0 +1,120 @@
package command
import (
"fmt"
"strings"
)
type JobRevertCommand struct {
Meta
formatter DataFormatter
}
func (c *JobRevertCommand) Help() string {
helpText := `
Usage: nomad job revert [options] <job>
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() + `
History Options:
-job-version <job version>
Revert to the given job version.
-detach
Return immediately instead of entering monitor mode. After job dispatch,
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) Run(args []string) int {
var detach, verbose bool
var versionStr string
flags := c.Meta.FlagSet("job history", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.StringVar(&versionStr, "job-version", "", "")
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 exactly one node
args = flags.Args()
if l := len(args); l < 1 || l > 2 {
c.Ui.Error(c.Help())
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]
// 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.Output(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
return 0
}
revertVersion, ok, err := parseVersion(versionStr)
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
}
// 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)
}

View File

@ -0,0 +1,34 @@
package command
import (
"strings"
"testing"
"github.com/mitchellh/cli"
)
func TestJobRevertCommand_Implements(t *testing.T) {
var _ cli.Command = &JobDispatchCommand{}
}
func TestJobRevertCommand_Fails(t *testing.T) {
ui := new(cli.MockUi)
cmd := &JobRevertCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) {
t.Fatalf("expected help output, got: %s", out)
}
ui.ErrorWriter.Reset()
if code := cmd.Run([]string{"-address=nope", "foo"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error listing jobs") {
t.Fatalf("expected failed query error, got: %s", out)
}
ui.ErrorWriter.Reset()
}

View File

@ -104,6 +104,11 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"job revert": func() (cli.Command, error) {
return &command.JobRevertCommand{
Meta: meta,
}, nil
},
"logs": func() (cli.Command, error) {
return &command.LogsCommand{
Meta: meta,

View File

@ -40,7 +40,7 @@ func RunCustom(args []string, commands map[string]cli.CommandFactory) int {
case "executor":
case "syslog":
case "operator raft", "operator raft list-peers", "operator raft remove-peer":
case "job dispatch", "job history":
case "job dispatch", "job history", "job revert":
case "fs ls", "fs cat", "fs stat":
case "check":
default: