217 lines
5.3 KiB
Go
217 lines
5.3 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/nomad/api/internal/testutil"
|
|
"github.com/shoenig/test/must"
|
|
"github.com/shoenig/test/wait"
|
|
)
|
|
|
|
func TestEvaluations_List(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
|
|
c, s := makeClient(t, nil, nil)
|
|
defer s.Stop()
|
|
e := c.Evaluations()
|
|
|
|
// Listing when nothing exists returns empty
|
|
result, qm, err := e.List(nil)
|
|
must.NoError(t, err)
|
|
must.Eq(t, 0, qm.LastIndex)
|
|
must.SliceEmpty(t, result)
|
|
|
|
// Register a job. This will create an evaluation.
|
|
jobs := c.Jobs()
|
|
job := testJob()
|
|
resp, wm, err := jobs.Register(job, nil)
|
|
must.NoError(t, err)
|
|
assertWriteMeta(t, wm)
|
|
|
|
// Check the evaluations again
|
|
result, qm, err = e.List(nil)
|
|
must.NoError(t, err)
|
|
assertQueryMeta(t, qm)
|
|
|
|
// if the eval fails fast there can be more than 1
|
|
// but they are in order of most recent first, so look at the last one
|
|
must.Positive(t, len(result))
|
|
idx := len(result) - 1
|
|
must.Eq(t, resp.EvalID, result[idx].ID)
|
|
|
|
// wait until the 2nd eval shows up before we try paging
|
|
var results []*Evaluation
|
|
|
|
f := func() error {
|
|
results, _, err = e.List(nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list evaluations: %w", err)
|
|
}
|
|
if len(results) < 2 {
|
|
return fmt.Errorf("fewer than 2 results, got: %d", len(results))
|
|
}
|
|
return nil
|
|
}
|
|
must.Wait(t, wait.InitialSuccess(wait.ErrorFunc(f)))
|
|
|
|
// query first page
|
|
result, qm, err = e.List(&QueryOptions{
|
|
PerPage: int32(1),
|
|
})
|
|
must.NoError(t, err)
|
|
must.Len(t, 1, result)
|
|
|
|
// query second page
|
|
result, qm, err = e.List(&QueryOptions{
|
|
PerPage: int32(1),
|
|
NextToken: qm.NextToken,
|
|
})
|
|
must.NoError(t, err)
|
|
must.Len(t, 1, result)
|
|
|
|
// Query evaluations using a filter.
|
|
results, _, err = e.List(&QueryOptions{
|
|
Filter: `TriggeredBy == "job-register"`,
|
|
})
|
|
must.Len(t, 1, result)
|
|
}
|
|
|
|
func TestEvaluations_PrefixList(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
|
|
c, s := makeClient(t, nil, nil)
|
|
defer s.Stop()
|
|
e := c.Evaluations()
|
|
|
|
// Listing when nothing exists returns empty
|
|
result, qm, err := e.PrefixList("abcdef")
|
|
must.NoError(t, err)
|
|
must.Eq(t, 0, qm.LastIndex)
|
|
must.SliceEmpty(t, result)
|
|
|
|
// Register a job. This will create an evaluation.
|
|
jobs := c.Jobs()
|
|
job := testJob()
|
|
resp, wm, err := jobs.Register(job, nil)
|
|
must.NoError(t, err)
|
|
assertWriteMeta(t, wm)
|
|
|
|
// Check the evaluations again
|
|
result, qm, err = e.PrefixList(resp.EvalID[:4])
|
|
must.NoError(t, err)
|
|
assertQueryMeta(t, qm)
|
|
|
|
// Check if we have the right list
|
|
must.Len(t, 1, result)
|
|
must.Eq(t, resp.EvalID, result[0].ID)
|
|
}
|
|
|
|
func TestEvaluations_Info(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
|
|
c, s := makeClient(t, nil, nil)
|
|
defer s.Stop()
|
|
e := c.Evaluations()
|
|
|
|
// Querying a nonexistent evaluation returns error
|
|
_, _, err := e.Info("8E231CF4-CA48-43FF-B694-5801E69E22FA", nil)
|
|
must.Error(t, err)
|
|
|
|
// Register a job. Creates a new evaluation.
|
|
jobs := c.Jobs()
|
|
job := testJob()
|
|
resp, wm, err := jobs.Register(job, nil)
|
|
must.NoError(t, err)
|
|
assertWriteMeta(t, wm)
|
|
|
|
// Try looking up by the new eval ID
|
|
result, qm, err := e.Info(resp.EvalID, nil)
|
|
must.NoError(t, err)
|
|
assertQueryMeta(t, qm)
|
|
|
|
// Check that we got the right result
|
|
must.NotNil(t, result)
|
|
must.Eq(t, resp.EvalID, result.ID)
|
|
|
|
// Register the job again to get a related eval
|
|
resp, wm, err = jobs.Register(job, nil)
|
|
evals, _, err := e.List(nil)
|
|
must.NoError(t, err)
|
|
|
|
// Find an eval that should have related evals
|
|
for _, eval := range evals {
|
|
if eval.NextEval != "" || eval.PreviousEval != "" || eval.BlockedEval != "" {
|
|
result, qm, err = e.Info(eval.ID, &QueryOptions{
|
|
Params: map[string]string{
|
|
"related": "true",
|
|
},
|
|
})
|
|
must.NoError(t, err)
|
|
assertQueryMeta(t, qm)
|
|
must.NotNil(t, result.RelatedEvals)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvaluations_Delete(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
|
|
testClient, testServer := makeClient(t, nil, nil)
|
|
defer testServer.Stop()
|
|
|
|
// Attempting to delete an evaluation when the eval broker is not paused
|
|
// should return an error.
|
|
wm, err := testClient.Evaluations().Delete([]string{"8E231CF4-CA48-43FF-B694-5801E69E22FA"}, nil)
|
|
must.Nil(t, wm)
|
|
must.ErrorContains(t, err, "eval broker is enabled")
|
|
|
|
// Pause the eval broker, and try to delete an evaluation that does not
|
|
// exist.
|
|
schedulerConfig, _, err := testClient.Operator().SchedulerGetConfiguration(nil)
|
|
must.NoError(t, err)
|
|
must.NotNil(t, schedulerConfig)
|
|
|
|
schedulerConfig.SchedulerConfig.PauseEvalBroker = true
|
|
schedulerConfigUpdated, _, err := testClient.Operator().SchedulerCASConfiguration(schedulerConfig.SchedulerConfig, nil)
|
|
must.NoError(t, err)
|
|
must.True(t, schedulerConfigUpdated.Updated)
|
|
|
|
wm, err = testClient.Evaluations().Delete([]string{"8E231CF4-CA48-43FF-B694-5801E69E22FA"}, nil)
|
|
must.ErrorContains(t, err, "eval not found")
|
|
}
|
|
|
|
func TestEvaluations_Allocations(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
c, s := makeClient(t, nil, nil)
|
|
defer s.Stop()
|
|
e := c.Evaluations()
|
|
|
|
// Returns empty if no allocations
|
|
allocs, qm, err := e.Allocations("8E231CF4-CA48-43FF-B694-5801E69E22FA", nil)
|
|
must.NoError(t, err)
|
|
must.Eq(t, 0, qm.LastIndex)
|
|
must.SliceEmpty(t, allocs)
|
|
}
|
|
|
|
func TestEvaluations_Sort(t *testing.T) {
|
|
testutil.Parallel(t)
|
|
evals := []*Evaluation{
|
|
{CreateIndex: 2},
|
|
{CreateIndex: 1},
|
|
{CreateIndex: 5},
|
|
}
|
|
sort.Sort(EvalIndexSort(evals))
|
|
|
|
expect := []*Evaluation{
|
|
{CreateIndex: 5},
|
|
{CreateIndex: 2},
|
|
{CreateIndex: 1},
|
|
}
|
|
must.Eq(t, expect, evals)
|
|
}
|