Update monitor func not to take a prefix (#9251)

The only user of monitor(evalID, true) was command/eval_status, and
eval_status had a duplicate of the prefix-handling code inside it, so in
all cases the complete evalID was being passed to monitor.

Given that, we can remove the prefix code from command/monitor, and
remove the boolean arg.
This commit is contained in:
Kris Hicks 2020-11-02 10:24:49 -08:00 committed by GitHub
parent 5d686a40be
commit 48a260fc33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 22 additions and 137 deletions

View File

@ -123,7 +123,7 @@ func (c *AllocStopCommand) Run(args []string) int {
}
mon := newMonitor(c.Ui, client, length)
return mon.monitor(resp.EvalID, false)
return mon.monitor(resp.EvalID)
}
func (a *AllocStopCommand) Synopsis() string {

View File

@ -135,5 +135,5 @@ func (c *DeploymentFailCommand) Run(args []string) int {
c.Ui.Output("")
mon := newMonitor(c.Ui, client, length)
return mon.monitor(u.EvalID, false)
return mon.monitor(u.EvalID)
}

View File

@ -144,5 +144,5 @@ func (c *DeploymentPromoteCommand) Run(args []string) int {
}
mon := newMonitor(c.Ui, client, length)
return mon.monitor(u.EvalID, false)
return mon.monitor(u.EvalID)
}

View File

@ -127,5 +127,5 @@ func (c *DeploymentResumeCommand) Run(args []string) int {
c.Ui.Output("")
mon := newMonitor(c.Ui, client, length)
return mon.monitor(u.EvalID, false)
return mon.monitor(u.EvalID)
}

View File

@ -127,5 +127,5 @@ func (c *DeploymentUnblockCommand) Run(args []string) int {
c.Ui.Output("")
mon := newMonitor(c.Ui, client, length)
return mon.monitor(u.EvalID, false)
return mon.monitor(u.EvalID)
}

View File

@ -175,7 +175,7 @@ func (c *EvalStatusCommand) Run(args []string) int {
// If we are in monitor mode, monitor and exit
if monitor {
mon := newMonitor(c.Ui, client, length)
return mon.monitor(evals[0].ID, true)
return mon.monitor(evals[0].ID)
}
// Prefix lookup matched a single evaluation

View File

@ -173,5 +173,5 @@ func (c *JobDispatchCommand) Run(args []string) int {
c.Ui.Output("")
mon := newMonitor(c.Ui, client, length)
return mon.monitor(resp.EvalID, false)
return mon.monitor(resp.EvalID)
}

View File

@ -124,5 +124,5 @@ func (c *JobEvalCommand) Run(args []string) int {
}
mon := newMonitor(c.Ui, client, length)
return mon.monitor(evalId, false)
return mon.monitor(evalId)
}

View File

@ -148,5 +148,5 @@ func (c *JobPeriodicForceCommand) Run(args []string) int {
// Detach was not specified, so start monitoring
mon := newMonitor(c.Ui, client, length)
return mon.monitor(evalID, false)
return mon.monitor(evalID)
}

View File

@ -163,5 +163,5 @@ func (c *JobPromoteCommand) Run(args []string) int {
}
mon := newMonitor(c.Ui, client, length)
return mon.monitor(u.EvalID, false)
return mon.monitor(u.EvalID)
}

View File

@ -164,5 +164,5 @@ func (c *JobRevertCommand) Run(args []string) int {
}
mon := newMonitor(c.Ui, client, length)
return mon.monitor(resp.EvalID, false)
return mon.monitor(resp.EvalID)
}

View File

@ -314,7 +314,7 @@ func (c *JobRunCommand) Run(args []string) int {
// Detach was not specified, so start monitoring
mon := newMonitor(c.Ui, client, length)
return mon.monitor(evalID, false)
return mon.monitor(evalID)
}

View File

@ -150,7 +150,7 @@ func (j *JobScaleCommand) Run(args []string) int {
// Create and monitor the evaluation.
mon := newMonitor(j.Ui, client, length)
return mon.monitor(resp.EvalID, false)
return mon.monitor(resp.EvalID)
}
// performGroupCheck performs logic to ensure the user specified the correct

View File

@ -387,6 +387,6 @@ func TestJobStatusCommand_RescheduleEvals(t *testing.T) {
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)
monErr := mon.monitor(evalId)
return monErr
}

View File

@ -206,5 +206,5 @@ func (c *JobStopCommand) Run(args []string) int {
// Start monitoring the stop eval
mon := newMonitor(c.Ui, client, length)
return mon.monitor(evalID, false)
return mon.monitor(evalID)
}

View File

@ -165,25 +165,19 @@ func (m *monitor) update(update *evalState) {
// monitor is used to start monitoring the given evaluation ID. It
// writes output directly to the monitor's ui, and returns the
// exit code for the command. If allowPrefix is false, monitor will only accept
// exact matching evalIDs.
// exit code for the command.
//
// The return code will be 0 on successful evaluation. If there are
// problems scheduling the job (impossible constraints, resources
// exhausted, etc), then the return code will be 2. For any other
// failures (API connectivity, internal errors, etc), the return code
// will be 1.
func (m *monitor) monitor(evalID string, allowPrefix bool) int {
func (m *monitor) monitor(evalID string) int {
// Track if we encounter a scheduling failure. This can only be
// detected while querying allocations, so we use this bool to
// carry that status into the return code.
var schedFailure bool
// The user may have specified a prefix as eval id. We need to lookup the
// full id from the database first. Since we do this in a loop we need a
// variable to keep track if we've already written the header message.
var headerWritten bool
// Add the initial pending state
m.update(newEvalState())
@ -191,51 +185,11 @@ func (m *monitor) monitor(evalID string, allowPrefix bool) int {
// Query the evaluation
eval, _, err := m.client.Evaluations().Info(evalID, nil)
if err != nil {
if !allowPrefix {
m.ui.Error(fmt.Sprintf("No evaluation with id %q found", evalID))
return 1
}
if len(evalID) == 1 {
m.ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
return 1
}
evalID = sanitizeUUIDPrefix(evalID)
evals, _, err := m.client.Evaluations().PrefixList(evalID)
if err != nil {
m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
return 1
}
if len(evals) == 0 {
m.ui.Error(fmt.Sprintf("No evaluation(s) with prefix or id %q found", evalID))
return 1
}
if len(evals) > 1 {
// Format the evaluations
out := make([]string, len(evals)+1)
out[0] = "ID|Priority|Type|Triggered By|Status"
for i, eval := range evals {
out[i+1] = fmt.Sprintf("%s|%d|%s|%s|%s",
limit(eval.ID, m.length),
eval.Priority,
eval.Type,
eval.TriggeredBy,
eval.Status)
}
m.ui.Output(fmt.Sprintf("Prefix matched multiple evaluations\n\n%s", formatList(out)))
return 0
}
// Prefix lookup matched a single evaluation
eval, _, err = m.client.Evaluations().Info(evals[0].ID, nil)
if err != nil {
m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err))
}
m.ui.Error(fmt.Sprintf("No evaluation with id %q found", evalID))
return 1
}
if !headerWritten {
m.ui.Info(fmt.Sprintf("Monitoring evaluation %q", limit(eval.ID, m.length)))
headerWritten = true
}
m.ui.Info(fmt.Sprintf("Monitoring evaluation %q", limit(eval.ID, m.length)))
// Create the new eval state.
state := newEvalState()
@ -319,7 +273,7 @@ func (m *monitor) monitor(evalID string, allowPrefix bool) int {
// Reset the state and monitor the new eval
m.state = newEvalState()
return m.monitor(eval.NextEval, allowPrefix)
return m.monitor(eval.NextEval)
}
break
}

View File

@ -191,7 +191,7 @@ func TestMonitor_Monitor(t *testing.T) {
doneCh := make(chan struct{})
go func() {
defer close(doneCh)
code = mon.monitor(resp.EvalID, false)
code = mon.monitor(resp.EvalID)
}()
// Wait for completion
@ -216,72 +216,3 @@ func TestMonitor_Monitor(t *testing.T) {
t.Fatalf("missing final status\n\n%s", out)
}
}
func TestMonitor_MonitorWithPrefix(t *testing.T) {
t.Parallel()
srv, client, _ := testServer(t, false, nil)
defer srv.Shutdown()
// Create the monitor
ui := cli.NewMockUi()
mon := newMonitor(ui, client, shortId)
// Submit a job - this creates a new evaluation we can monitor
job := testJob("job1")
resp, _, err := client.Jobs().Register(job, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
// Start monitoring the eval
var code int
doneCh := make(chan struct{})
go func() {
defer close(doneCh)
code = mon.monitor(resp.EvalID[:13], true)
}()
// Wait for completion
select {
case <-doneCh:
case <-time.After(5 * time.Second):
t.Fatalf("eval monitor took too long")
}
// Check the return code. We should get exit code 2 as there
// would be a scheduling problem on the test server (no clients).
if code != 2 {
t.Fatalf("expect exit 2, got: %d", code)
}
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, resp.EvalID[:8]) {
t.Fatalf("missing eval\n\n%s", out)
}
if strings.Contains(out, resp.EvalID) {
t.Fatalf("expected truncated eval id, got: %s", out)
}
if !strings.Contains(out, "finished with status") {
t.Fatalf("missing final status\n\n%s", out)
}
// Fail on identifier with too few characters
code = mon.monitor(resp.EvalID[:1], true)
if code != 1 {
t.Fatalf("expect exit 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "must contain at least two characters.") {
t.Fatalf("expected too few characters error, got: %s", out)
}
ui.ErrorWriter.Reset()
code = mon.monitor(resp.EvalID[:3], true)
if code != 2 {
t.Fatalf("expect exit 2, got: %d", code)
}
if out := ui.OutputWriter.String(); !strings.Contains(out, "Monitoring evaluation") {
t.Fatalf("expected evaluation monitoring output, got: %s", out)
}
}