diff --git a/command/job_status.go b/command/job_status.go index 154dd4dc2..46e8a02ef 100644 --- a/command/job_status.go +++ b/command/job_status.go @@ -566,7 +566,7 @@ func (c *JobStatusCommand) outputReschedulingEvals(client *api.Client, allocList var delayedEvalInfos []string taskGroups := make([]string, 0, len(followUpEvalIds)) - for taskGroup, _ := range followUpEvalIds { + for taskGroup := range followUpEvalIds { taskGroups = append(taskGroups, taskGroup) } sort.Strings(taskGroups) diff --git a/command/job_status_test.go b/command/job_status_test.go index 4a07ea71f..1af5567b8 100644 --- a/command/job_status_test.go +++ b/command/job_status_test.go @@ -1,15 +1,20 @@ package command import ( + "fmt" "strings" "testing" + "time" "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/command/agent" "github.com/hashicorp/nomad/nomad/mock" + "github.com/hashicorp/nomad/nomad/structs" + "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" "github.com/posener/complete" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestJobStatusCommand_Implements(t *testing.T) { @@ -276,6 +281,59 @@ func TestJobStatusCommand_WithAccessPolicy(t *testing.T) { } } +func TestJobStatusCommand_RescheduleEvals(t *testing.T) { + t.Parallel() + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + // Wait for a node to be ready + testutil.WaitForResult(func() (bool, error) { + nodes, _, err := client.Nodes().List(nil) + if err != nil { + return false, err + } + for _, node := range nodes { + if node.Status == structs.NodeStatusReady { + return true, nil + } + } + return false, fmt.Errorf("no ready nodes") + }, func(err error) { + t.Fatalf("err: %v", err) + }) + + ui := new(cli.MockUi) + cmd := &JobStatusCommand{Meta: Meta{Ui: ui, flagAddress: url}} + + require := require.New(t) + state := srv.Agent.Server().State() + + // Create state store objects for job, alloc and followup eval with a future WaitUntil value + j := mock.Job() + require.Nil(state.UpsertJob(900, j)) + + e := mock.Eval() + e.WaitUntil = time.Now().Add(1 * time.Hour) + require.Nil(state.UpsertEvals(902, []*structs.Evaluation{e})) + a := mock.Alloc() + a.Job = j + a.JobID = j.ID + a.TaskGroup = j.TaskGroups[0].Name + a.FollowupEvalID = e.ID + a.Metrics = &structs.AllocMetric{} + a.DesiredStatus = structs.AllocDesiredStatusRun + a.ClientStatus = structs.AllocClientStatusRunning + require.Nil(state.UpsertAllocs(1000, []*structs.Allocation{a})) + + // Query jobs with prefix match + if code := cmd.Run([]string{"-address=" + url, j.ID}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out := ui.OutputWriter.String() + require.Contains(out, "Upcoming Evaluations") + require.Contains(out, e.ID) +} + func waitForSuccess(ui cli.Ui, client *api.Client, length int, t *testing.T, evalId string) int { mon := newMonitor(ui, client, length) monErr := mon.monitor(evalId, false)