mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
Divest api/ package of deps elsewhere in the nomad repo. (#5488)
* Divest api/ package of deps elsewhere in the nomad repo. This will allow making api/ a module without then pulling in the external repo, leading to a package name conflict. This required some migration of tests to an apitests/ folder (can be moved anywhere as it has no deps on it). It also required some duplication of code, notably some test helpers from api/ -> apitests/ and part (but not all) of testutil/ -> api/testutil/. Once there's more separation and an e.g. sdk/ folder those can be removed in favor of a dep on the sdk/ folder, provided the sdk/ folder doesn't depend on api/ or /. * Also remove consul dep from api/ package * Fix stupid linters * Some restructuring
This commit is contained in:
56
internal/testing/apitests/api_test.go
Normal file
56
internal/testing/apitests/api_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/testutil"
|
||||
)
|
||||
|
||||
type configCallback func(c *api.Config)
|
||||
|
||||
// seen is used to track which tests we have already marked as parallel
|
||||
var seen map[*testing.T]struct{}
|
||||
|
||||
func init() {
|
||||
seen = make(map[*testing.T]struct{})
|
||||
}
|
||||
|
||||
func makeACLClient(t *testing.T, cb1 configCallback,
|
||||
cb2 testutil.ServerConfigCallback) (*api.Client, *testutil.TestServer, *api.ACLToken) {
|
||||
client, server := makeClient(t, cb1, func(c *testutil.TestServerConfig) {
|
||||
c.ACL.Enabled = true
|
||||
if cb2 != nil {
|
||||
cb2(c)
|
||||
}
|
||||
})
|
||||
|
||||
// Get the root token
|
||||
root, _, err := client.ACLTokens().Bootstrap(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to bootstrap ACLs: %v", err)
|
||||
}
|
||||
client.SetSecretID(root.SecretID)
|
||||
return client, server, root
|
||||
}
|
||||
|
||||
func makeClient(t *testing.T, cb1 configCallback,
|
||||
cb2 testutil.ServerConfigCallback) (*api.Client, *testutil.TestServer) {
|
||||
// Make client config
|
||||
conf := api.DefaultConfig()
|
||||
if cb1 != nil {
|
||||
cb1(conf)
|
||||
}
|
||||
|
||||
// Create server
|
||||
server := testutil.NewTestServer(t, cb2)
|
||||
conf.Address = "http://" + server.HTTPAddr
|
||||
|
||||
// Create client
|
||||
client, err := api.NewClient(conf)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
return client, server
|
||||
}
|
||||
85
internal/testing/apitests/jobs_test.go
Normal file
85
internal/testing/apitests/jobs_test.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/nomad/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJobs_Parse(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
|
||||
jobs := c.Jobs()
|
||||
|
||||
checkJob := func(job *api.Job, expectedRegion string) {
|
||||
if job == nil {
|
||||
t.Fatal("job should not be nil")
|
||||
}
|
||||
|
||||
region := job.Region
|
||||
|
||||
if region == nil {
|
||||
if expectedRegion != "" {
|
||||
t.Fatalf("expected job region to be '%s' but was unset", expectedRegion)
|
||||
}
|
||||
} else {
|
||||
if expectedRegion != *region {
|
||||
t.Fatalf("expected job region '%s', but got '%s'", expectedRegion, *region)
|
||||
}
|
||||
}
|
||||
}
|
||||
job, err := jobs.ParseHCL(mock.HCL(), true)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
checkJob(job, "global")
|
||||
|
||||
job, err = jobs.ParseHCL(mock.HCL(), false)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
checkJob(job, "")
|
||||
}
|
||||
|
||||
func TestJobs_Summary_WithACL(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
|
||||
c, s, root := makeACLClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
jobs := c.Jobs()
|
||||
|
||||
invalidToken := mock.ACLToken()
|
||||
|
||||
// Registering with an invalid token should fail
|
||||
c.SetSecretID(invalidToken.SecretID)
|
||||
job := testJob()
|
||||
_, _, err := jobs.Register(job, nil)
|
||||
assert.NotNil(err)
|
||||
|
||||
// Register with token should succeed
|
||||
c.SetSecretID(root.SecretID)
|
||||
resp2, wm, err := jobs.Register(job, nil)
|
||||
assert.Nil(err)
|
||||
assert.NotNil(resp2)
|
||||
assert.NotEqual("", resp2.EvalID)
|
||||
assertWriteMeta(t, wm)
|
||||
|
||||
// Query the job summary with an invalid token should fail
|
||||
c.SetSecretID(invalidToken.SecretID)
|
||||
result, _, err := jobs.Summary(*job.ID, nil)
|
||||
assert.NotNil(err)
|
||||
|
||||
// Query the job summary with a valid token should succeed
|
||||
c.SetSecretID(root.SecretID)
|
||||
result, qm, err := jobs.Summary(*job.ID, nil)
|
||||
assert.Nil(err)
|
||||
assertQueryMeta(t, qm)
|
||||
|
||||
// Check that the result is what we expect
|
||||
assert.Equal(*job.ID, result.JobID)
|
||||
}
|
||||
33
internal/testing/apitests/nodes_test.go
Normal file
33
internal/testing/apitests/nodes_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/helper/uuid"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNodes_GC(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
nodes := c.Nodes()
|
||||
|
||||
err := nodes.GC(uuid.Generate(), nil)
|
||||
require.NotNil(err)
|
||||
require.True(structs.IsErrUnknownNode(err))
|
||||
}
|
||||
|
||||
func TestNodes_GcAlloc(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
nodes := c.Nodes()
|
||||
|
||||
err := nodes.GcAlloc(uuid.Generate(), nil)
|
||||
require.NotNil(err)
|
||||
require.True(structs.IsErrUnknownAllocation(err))
|
||||
}
|
||||
101
internal/testing/apitests/operator_autopilot_test.go
Normal file
101
internal/testing/apitests/operator_autopilot_test.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/consul/testutil/retry"
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPI_OperatorAutopilotGetSetConfiguration(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
|
||||
operator := c.Operator()
|
||||
var config *api.AutopilotConfiguration
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
var err error
|
||||
config, _, err = operator.AutopilotGetConfiguration(nil)
|
||||
r.Check(err)
|
||||
})
|
||||
require.True(config.CleanupDeadServers)
|
||||
|
||||
// Change a config setting
|
||||
newConf := &api.AutopilotConfiguration{CleanupDeadServers: false}
|
||||
_, err := operator.AutopilotSetConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
|
||||
config, _, err = operator.AutopilotGetConfiguration(nil)
|
||||
require.Nil(err)
|
||||
require.False(config.CleanupDeadServers)
|
||||
}
|
||||
|
||||
func TestAPI_OperatorAutopilotCASConfiguration(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
|
||||
operator := c.Operator()
|
||||
var config *api.AutopilotConfiguration
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
var err error
|
||||
config, _, err = operator.AutopilotGetConfiguration(nil)
|
||||
r.Check(err)
|
||||
})
|
||||
require.True(config.CleanupDeadServers)
|
||||
|
||||
// Pass an invalid ModifyIndex
|
||||
{
|
||||
newConf := &api.AutopilotConfiguration{
|
||||
CleanupDeadServers: false,
|
||||
ModifyIndex: config.ModifyIndex - 1,
|
||||
}
|
||||
resp, _, err := operator.AutopilotCASConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
require.False(resp)
|
||||
}
|
||||
|
||||
// Pass a valid ModifyIndex
|
||||
{
|
||||
newConf := &api.AutopilotConfiguration{
|
||||
CleanupDeadServers: false,
|
||||
ModifyIndex: config.ModifyIndex,
|
||||
}
|
||||
resp, _, err := operator.AutopilotCASConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
require.True(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPI_OperatorAutopilotServerHealth(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
|
||||
c.Server.RaftProtocol = 3
|
||||
})
|
||||
defer s.Stop()
|
||||
|
||||
operator := c.Operator()
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
out, _, err := operator.AutopilotServerHealth(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(out.Servers) != 1 ||
|
||||
!out.Servers[0].Healthy ||
|
||||
out.Servers[0].Name != fmt.Sprintf("%s.global", s.Config.NodeName) {
|
||||
return false, fmt.Errorf("%v", out)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %v", err)
|
||||
})
|
||||
}
|
||||
76
internal/testing/apitests/operator_test.go
Normal file
76
internal/testing/apitests/operator_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/testutil/retry"
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPI_OperatorSchedulerGetSetConfiguration(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
|
||||
operator := c.Operator()
|
||||
var config *api.SchedulerConfigurationResponse
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
var err error
|
||||
config, _, err = operator.SchedulerGetConfiguration(nil)
|
||||
r.Check(err)
|
||||
})
|
||||
require.True(config.SchedulerConfig.PreemptionConfig.SystemSchedulerEnabled)
|
||||
|
||||
// Change a config setting
|
||||
newConf := &api.SchedulerConfiguration{PreemptionConfig: api.PreemptionConfig{SystemSchedulerEnabled: false}}
|
||||
resp, wm, err := operator.SchedulerSetConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
require.NotZero(wm.LastIndex)
|
||||
require.False(resp.Updated)
|
||||
|
||||
config, _, err = operator.SchedulerGetConfiguration(nil)
|
||||
require.Nil(err)
|
||||
require.False(config.SchedulerConfig.PreemptionConfig.SystemSchedulerEnabled)
|
||||
}
|
||||
|
||||
func TestAPI_OperatorSchedulerCASConfiguration(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
|
||||
operator := c.Operator()
|
||||
var config *api.SchedulerConfigurationResponse
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
var err error
|
||||
config, _, err = operator.SchedulerGetConfiguration(nil)
|
||||
r.Check(err)
|
||||
})
|
||||
require.True(config.SchedulerConfig.PreemptionConfig.SystemSchedulerEnabled)
|
||||
|
||||
// Pass an invalid ModifyIndex
|
||||
{
|
||||
newConf := &api.SchedulerConfiguration{
|
||||
PreemptionConfig: api.PreemptionConfig{SystemSchedulerEnabled: false},
|
||||
ModifyIndex: config.SchedulerConfig.ModifyIndex - 1,
|
||||
}
|
||||
resp, wm, err := operator.SchedulerCASConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
require.NotZero(wm.LastIndex)
|
||||
require.False(resp.Updated)
|
||||
}
|
||||
|
||||
// Pass a valid ModifyIndex
|
||||
{
|
||||
newConf := &api.SchedulerConfiguration{
|
||||
PreemptionConfig: api.PreemptionConfig{SystemSchedulerEnabled: false},
|
||||
ModifyIndex: config.SchedulerConfig.ModifyIndex,
|
||||
}
|
||||
resp, wm, err := operator.SchedulerCASConfiguration(newConf, nil)
|
||||
require.Nil(err)
|
||||
require.NotZero(wm.LastIndex)
|
||||
require.True(resp.Updated)
|
||||
}
|
||||
}
|
||||
102
internal/testing/apitests/structsync_test.go
Normal file
102
internal/testing/apitests/structsync_test.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Tests that api and struct values are equivalent
|
||||
//
|
||||
// Given that vendoring libraries prune tests by default, test dependencies
|
||||
// aren't leaked to clients of the package - so it should be safe to add
|
||||
// such dependency without affecting api clients.
|
||||
|
||||
func TestDefaultResourcesAreInSync(t *testing.T) {
|
||||
apiR := api.DefaultResources()
|
||||
structsR := structs.DefaultResources()
|
||||
|
||||
require.EqualValues(t, *structsR, toStructsResource(t, apiR))
|
||||
|
||||
// match after canonicalization
|
||||
apiR.Canonicalize()
|
||||
structsR.Canonicalize()
|
||||
require.EqualValues(t, *structsR, toStructsResource(t, apiR))
|
||||
}
|
||||
|
||||
func TestMinResourcesAreInSync(t *testing.T) {
|
||||
apiR := api.MinResources()
|
||||
structsR := structs.MinResources()
|
||||
|
||||
require.EqualValues(t, *structsR, toStructsResource(t, apiR))
|
||||
|
||||
// match after canonicalization
|
||||
apiR.Canonicalize()
|
||||
structsR.Canonicalize()
|
||||
require.EqualValues(t, *structsR, toStructsResource(t, apiR))
|
||||
}
|
||||
|
||||
func TestNewDefaultRescheulePolicyInSync(t *testing.T) {
|
||||
cases := []struct {
|
||||
typ string
|
||||
expected structs.ReschedulePolicy
|
||||
}{
|
||||
{"service", structs.DefaultServiceJobReschedulePolicy},
|
||||
{"batch", structs.DefaultBatchJobReschedulePolicy},
|
||||
{"system", structs.ReschedulePolicy{}},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.typ, func(t *testing.T) {
|
||||
apiP := api.NewDefaultReschedulePolicy(c.typ)
|
||||
|
||||
var found structs.ReschedulePolicy
|
||||
toStructs(t, &found, apiP)
|
||||
|
||||
require.EqualValues(t, c.expected, found)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDefaultRestartPolicyInSync(t *testing.T) {
|
||||
cases := []struct {
|
||||
typ string
|
||||
expected structs.RestartPolicy
|
||||
}{
|
||||
{"service", structs.DefaultServiceJobRestartPolicy},
|
||||
{"batch", structs.DefaultBatchJobRestartPolicy},
|
||||
{"system", structs.DefaultServiceJobRestartPolicy},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.typ, func(t *testing.T) {
|
||||
job := api.Job{Type: &c.typ}
|
||||
var tg api.TaskGroup
|
||||
tg.Canonicalize(&job)
|
||||
|
||||
apiP := tg.RestartPolicy
|
||||
|
||||
var found structs.RestartPolicy
|
||||
toStructs(t, &found, apiP)
|
||||
|
||||
require.EqualValues(t, c.expected, found)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func toStructsResource(t *testing.T, in *api.Resources) structs.Resources {
|
||||
var out structs.Resources
|
||||
toStructs(t, &out, in)
|
||||
return out
|
||||
}
|
||||
|
||||
func toStructs(t *testing.T, out, in interface{}) {
|
||||
bytes, err := json.Marshal(in)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = json.Unmarshal(bytes, &out)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
171
internal/testing/apitests/tasks_test.go
Normal file
171
internal/testing/apitests/tasks_test.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Verifies that reschedule policy is merged correctly
|
||||
func TestTaskGroup_Canonicalize_ReschedulePolicy(t *testing.T) {
|
||||
type testCase struct {
|
||||
desc string
|
||||
jobReschedulePolicy *api.ReschedulePolicy
|
||||
taskReschedulePolicy *api.ReschedulePolicy
|
||||
expected *api.ReschedulePolicy
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
desc: "Default",
|
||||
jobReschedulePolicy: nil,
|
||||
taskReschedulePolicy: nil,
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(structs.DefaultBatchJobReschedulePolicy.Attempts),
|
||||
Interval: timeToPtr(structs.DefaultBatchJobReschedulePolicy.Interval),
|
||||
Delay: timeToPtr(structs.DefaultBatchJobReschedulePolicy.Delay),
|
||||
DelayFunction: stringToPtr(structs.DefaultBatchJobReschedulePolicy.DelayFunction),
|
||||
MaxDelay: timeToPtr(structs.DefaultBatchJobReschedulePolicy.MaxDelay),
|
||||
Unlimited: boolToPtr(structs.DefaultBatchJobReschedulePolicy.Unlimited),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Empty job reschedule policy",
|
||||
jobReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(0),
|
||||
Interval: timeToPtr(0),
|
||||
Delay: timeToPtr(0),
|
||||
MaxDelay: timeToPtr(0),
|
||||
DelayFunction: stringToPtr(""),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
taskReschedulePolicy: nil,
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(0),
|
||||
Interval: timeToPtr(0),
|
||||
Delay: timeToPtr(0),
|
||||
MaxDelay: timeToPtr(0),
|
||||
DelayFunction: stringToPtr(""),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Inherit from job",
|
||||
jobReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
Interval: timeToPtr(20 * time.Second),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
taskReschedulePolicy: nil,
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
Interval: timeToPtr(20 * time.Second),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Set in task",
|
||||
jobReschedulePolicy: nil,
|
||||
taskReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(5),
|
||||
Interval: timeToPtr(2 * time.Minute),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(5),
|
||||
Interval: timeToPtr(2 * time.Minute),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Merge from job",
|
||||
jobReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
},
|
||||
taskReschedulePolicy: &api.ReschedulePolicy{
|
||||
Interval: timeToPtr(5 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
Interval: timeToPtr(5 * time.Minute),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(10 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Override from group",
|
||||
jobReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
MaxDelay: timeToPtr(10 * time.Second),
|
||||
},
|
||||
taskReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(5),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(20 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(5),
|
||||
Interval: timeToPtr(structs.DefaultBatchJobReschedulePolicy.Interval),
|
||||
Delay: timeToPtr(20 * time.Second),
|
||||
MaxDelay: timeToPtr(20 * time.Minute),
|
||||
DelayFunction: stringToPtr("constant"),
|
||||
Unlimited: boolToPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Attempts from job, default interval",
|
||||
jobReschedulePolicy: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
},
|
||||
taskReschedulePolicy: nil,
|
||||
expected: &api.ReschedulePolicy{
|
||||
Attempts: intToPtr(1),
|
||||
Interval: timeToPtr(structs.DefaultBatchJobReschedulePolicy.Interval),
|
||||
Delay: timeToPtr(structs.DefaultBatchJobReschedulePolicy.Delay),
|
||||
DelayFunction: stringToPtr(structs.DefaultBatchJobReschedulePolicy.DelayFunction),
|
||||
MaxDelay: timeToPtr(structs.DefaultBatchJobReschedulePolicy.MaxDelay),
|
||||
Unlimited: boolToPtr(structs.DefaultBatchJobReschedulePolicy.Unlimited),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
job := &api.Job{
|
||||
ID: stringToPtr("test"),
|
||||
Reschedule: tc.jobReschedulePolicy,
|
||||
Type: stringToPtr(api.JobTypeBatch),
|
||||
}
|
||||
job.Canonicalize()
|
||||
tg := &api.TaskGroup{
|
||||
Name: stringToPtr("foo"),
|
||||
ReschedulePolicy: tc.taskReschedulePolicy,
|
||||
}
|
||||
tg.Canonicalize(job)
|
||||
assert.Equal(t, tc.expected, tg.ReschedulePolicy)
|
||||
})
|
||||
}
|
||||
}
|
||||
83
internal/testing/apitests/util_test.go
Normal file
83
internal/testing/apitests/util_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package apitests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
)
|
||||
|
||||
// boolToPtr returns the pointer to a boolean
|
||||
func boolToPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// intToPtr returns the pointer to an int
|
||||
func intToPtr(i int) *int {
|
||||
return &i
|
||||
}
|
||||
|
||||
// timeToPtr returns the pointer to a time stamp
|
||||
func timeToPtr(t time.Duration) *time.Duration {
|
||||
return &t
|
||||
}
|
||||
|
||||
// stringToPtr returns the pointer to a string
|
||||
func stringToPtr(str string) *string {
|
||||
return &str
|
||||
}
|
||||
|
||||
func assertQueryMeta(t *testing.T, qm *api.QueryMeta) {
|
||||
t.Helper()
|
||||
if qm.LastIndex == 0 {
|
||||
t.Fatalf("bad index: %d", qm.LastIndex)
|
||||
}
|
||||
if !qm.KnownLeader {
|
||||
t.Fatalf("expected known leader, got none")
|
||||
}
|
||||
}
|
||||
|
||||
func assertWriteMeta(t *testing.T, wm *api.WriteMeta) {
|
||||
t.Helper()
|
||||
if wm.LastIndex == 0 {
|
||||
t.Fatalf("bad index: %d", wm.LastIndex)
|
||||
}
|
||||
}
|
||||
|
||||
func testJob() *api.Job {
|
||||
task := api.NewTask("task1", "exec").
|
||||
SetConfig("command", "/bin/sleep").
|
||||
Require(&api.Resources{
|
||||
CPU: intToPtr(100),
|
||||
MemoryMB: intToPtr(256),
|
||||
}).
|
||||
SetLogConfig(&api.LogConfig{
|
||||
MaxFiles: intToPtr(1),
|
||||
MaxFileSizeMB: intToPtr(2),
|
||||
})
|
||||
|
||||
group := api.NewTaskGroup("group1", 1).
|
||||
AddTask(task).
|
||||
RequireDisk(&api.EphemeralDisk{
|
||||
SizeMB: intToPtr(25),
|
||||
})
|
||||
|
||||
job := api.NewBatchJob("job1", "redis", "region1", 1).
|
||||
AddDatacenter("dc1").
|
||||
AddTaskGroup(group)
|
||||
|
||||
return job
|
||||
}
|
||||
|
||||
// conversions utils only used for testing
|
||||
// added here to avoid linter warning
|
||||
|
||||
// int64ToPtr returns the pointer to an int
|
||||
func int64ToPtr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// float64ToPtr returns the pointer to an float64
|
||||
func float64ToPtr(f float64) *float64 {
|
||||
return &f
|
||||
}
|
||||
Reference in New Issue
Block a user