2018-12-20 03:25:32 +00:00
|
|
|
package e2eutil
|
|
|
|
|
|
|
|
import (
|
2019-01-08 22:37:08 +00:00
|
|
|
"fmt"
|
2019-01-04 13:53:50 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2018-12-20 03:25:32 +00:00
|
|
|
"github.com/hashicorp/nomad/api"
|
|
|
|
"github.com/hashicorp/nomad/helper"
|
|
|
|
"github.com/hashicorp/nomad/jobspec"
|
2019-01-18 04:32:45 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2018-12-20 03:25:32 +00:00
|
|
|
"github.com/hashicorp/nomad/testutil"
|
2019-01-26 00:51:20 +00:00
|
|
|
"github.com/kr/pretty"
|
2018-12-20 03:25:32 +00:00
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// retries is used to control how many times to retry checking if the cluster has a leader yet
|
|
|
|
const retries = 500
|
|
|
|
|
|
|
|
func WaitForLeader(t *testing.T, nomadClient *api.Client) {
|
|
|
|
statusAPI := nomadClient.Status()
|
|
|
|
|
|
|
|
testutil.WaitForResultRetries(retries, func() (bool, error) {
|
|
|
|
leader, err := statusAPI.Leader()
|
|
|
|
return leader != "", err
|
|
|
|
}, func(err error) {
|
|
|
|
t.Fatalf("failed to find leader: %v", err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-01-08 22:37:08 +00:00
|
|
|
// WaitForNodesReady waits until at least `nodes` number of nodes are ready or
|
|
|
|
// fails the test.
|
2019-01-03 22:16:20 +00:00
|
|
|
func WaitForNodesReady(t *testing.T, nomadClient *api.Client, nodes int) {
|
|
|
|
nodesAPI := nomadClient.Nodes()
|
|
|
|
|
|
|
|
testutil.WaitForResultRetries(retries, func() (bool, error) {
|
2019-01-18 04:32:45 +00:00
|
|
|
defer time.Sleep(time.Millisecond * 100)
|
2019-01-03 22:16:20 +00:00
|
|
|
nodesList, _, err := nodesAPI.List(nil)
|
2019-01-08 22:37:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("error listing nodes: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-01-03 22:16:20 +00:00
|
|
|
eligibleNodes := 0
|
|
|
|
for _, node := range nodesList {
|
|
|
|
if node.Status == "ready" {
|
|
|
|
eligibleNodes++
|
|
|
|
}
|
|
|
|
}
|
2019-01-08 22:37:08 +00:00
|
|
|
|
|
|
|
return eligibleNodes >= nodes, fmt.Errorf("only %d nodes ready (wanted at least %d)", eligibleNodes, nodes)
|
2019-01-03 22:16:20 +00:00
|
|
|
}, func(err error) {
|
|
|
|
t.Fatalf("failed to get enough ready nodes: %v", err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-05-20 14:54:28 +00:00
|
|
|
func RegisterAllocs(t *testing.T, nomadClient *api.Client, jobFile string, jobID string) []*api.AllocationListStub {
|
2018-12-20 03:25:32 +00:00
|
|
|
// Parse job
|
|
|
|
job, err := jobspec.ParseFile(jobFile)
|
2019-01-18 04:32:45 +00:00
|
|
|
require := require.New(t)
|
2018-12-20 03:25:32 +00:00
|
|
|
require.Nil(err)
|
2019-01-03 22:16:20 +00:00
|
|
|
job.ID = helper.StringToPtr(jobID)
|
2018-12-20 03:25:32 +00:00
|
|
|
|
|
|
|
// Register job
|
2019-09-10 17:45:16 +00:00
|
|
|
var idx uint64
|
2018-12-20 03:25:32 +00:00
|
|
|
jobs := nomadClient.Jobs()
|
2019-01-26 00:51:20 +00:00
|
|
|
testutil.WaitForResult(func() (bool, error) {
|
2019-09-10 17:45:16 +00:00
|
|
|
resp, meta, err := jobs.Register(job, nil)
|
2019-01-26 00:51:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
2019-09-10 17:45:16 +00:00
|
|
|
idx = meta.LastIndex
|
2019-01-26 00:51:20 +00:00
|
|
|
return resp.EvalID != "", fmt.Errorf("expected EvalID:%s", pretty.Sprint(resp))
|
|
|
|
}, func(err error) {
|
|
|
|
require.NoError(err)
|
|
|
|
})
|
2018-12-20 03:25:32 +00:00
|
|
|
|
2019-09-10 17:45:16 +00:00
|
|
|
allocs, _, _ := jobs.Allocations(jobID, false, &api.QueryOptions{WaitIndex: idx})
|
2019-05-20 14:54:28 +00:00
|
|
|
return allocs
|
|
|
|
}
|
|
|
|
|
|
|
|
func RegisterAndWaitForAllocs(t *testing.T, nomadClient *api.Client, jobFile string, jobID string) []*api.AllocationListStub {
|
|
|
|
require := require.New(t)
|
|
|
|
g := NewGomegaWithT(t)
|
|
|
|
jobs := nomadClient.Jobs()
|
|
|
|
|
2019-05-20 19:10:32 +00:00
|
|
|
// Start allocations
|
|
|
|
RegisterAllocs(t, nomadClient, jobFile, jobID)
|
|
|
|
|
2018-12-20 03:25:32 +00:00
|
|
|
// Wrap in retry to wait until placement
|
|
|
|
g.Eventually(func() []*api.AllocationListStub {
|
|
|
|
// Look for allocations
|
2019-05-20 14:54:28 +00:00
|
|
|
allocs, _, _ := jobs.Allocations(jobID, false, nil)
|
2018-12-20 03:25:32 +00:00
|
|
|
return allocs
|
2019-01-03 20:02:02 +00:00
|
|
|
}, 30*time.Second, time.Second).ShouldNot(BeEmpty())
|
2018-12-20 03:25:32 +00:00
|
|
|
|
2019-05-20 14:54:28 +00:00
|
|
|
allocs, _, err := jobs.Allocations(jobID, false, nil)
|
|
|
|
require.NoError(err)
|
2019-01-03 22:16:20 +00:00
|
|
|
return allocs
|
2018-12-20 03:25:32 +00:00
|
|
|
}
|
2019-01-18 04:32:45 +00:00
|
|
|
|
|
|
|
func WaitForAllocRunning(t *testing.T, nomadClient *api.Client, allocID string) {
|
|
|
|
testutil.WaitForResultRetries(retries, func() (bool, error) {
|
2019-01-23 19:09:49 +00:00
|
|
|
time.Sleep(time.Millisecond * 100)
|
2019-01-18 04:32:45 +00:00
|
|
|
alloc, _, err := nomadClient.Allocations().Info(allocID, nil)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return alloc.ClientStatus == structs.AllocClientStatusRunning, fmt.Errorf("expected status running, but was: %s", alloc.ClientStatus)
|
|
|
|
}, func(err error) {
|
|
|
|
t.Fatalf("failed to wait on alloc: %v", err)
|
|
|
|
})
|
|
|
|
}
|
2019-05-20 14:54:28 +00:00
|
|
|
|
2019-06-04 18:31:42 +00:00
|
|
|
func DeploymentsForJob(t *testing.T, nomadClient *api.Client, jobID string) []*api.Deployment {
|
2019-06-04 15:25:18 +00:00
|
|
|
ds, _, err := nomadClient.Deployments().List(nil)
|
2019-06-04 18:31:42 +00:00
|
|
|
require.NoError(t, err)
|
2019-06-04 15:25:18 +00:00
|
|
|
|
|
|
|
out := []*api.Deployment{}
|
|
|
|
for _, d := range ds {
|
|
|
|
if d.JobID == jobID {
|
|
|
|
out = append(out, d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
2019-05-20 14:54:28 +00:00
|
|
|
func WaitForDeployment(t *testing.T, nomadClient *api.Client, deployID string, status string, statusDesc string) {
|
|
|
|
testutil.WaitForResultRetries(retries, func() (bool, error) {
|
|
|
|
time.Sleep(time.Millisecond * 100)
|
|
|
|
deploy, _, err := nomadClient.Deployments().Info(deployID, nil)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if deploy.Status == status && deploy.StatusDescription == statusDesc {
|
|
|
|
return true, nil
|
|
|
|
}
|
2019-05-20 17:27:28 +00:00
|
|
|
return false, fmt.Errorf("expected status %s \"%s\", but got: %s \"%s\"",
|
|
|
|
status,
|
|
|
|
statusDesc,
|
2019-06-04 15:25:18 +00:00
|
|
|
deploy.Status,
|
|
|
|
deploy.StatusDescription,
|
2019-05-20 17:27:28 +00:00
|
|
|
)
|
2019-05-20 14:54:28 +00:00
|
|
|
|
|
|
|
}, func(err error) {
|
2019-05-21 13:21:44 +00:00
|
|
|
t.Fatalf("failed to wait on deployment: %v", err)
|
2019-05-20 14:54:28 +00:00
|
|
|
})
|
|
|
|
}
|