nomad: move state and mocks into shared packages

This commit is contained in:
Armon Dadgar
2015-08-11 14:27:14 -07:00
parent f8cca6812c
commit 4f6d7e125a
18 changed files with 311 additions and 263 deletions

View File

@@ -5,6 +5,7 @@ import (
"testing"
"github.com/hashicorp/net-rpc-msgpackrpc"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -16,7 +17,7 @@ func TestClientEndpoint_Register(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
node := mockNode()
node := mock.Node()
req := &structs.NodeRegisterRequest{
Node: node,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -52,7 +53,7 @@ func TestClientEndpoint_Deregister(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
node := mockNode()
node := mock.Node()
reg := &structs.NodeRegisterRequest{
Node: node,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -95,7 +96,7 @@ func TestClientEndpoint_UpdateStatus(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
node := mockNode()
node := mock.Node()
reg := &structs.NodeRegisterRequest{
Node: node,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -142,7 +143,7 @@ func TestClientEndpoint_GetNode(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
node := mockNode()
node := mock.Node()
reg := &structs.NodeRegisterRequest{
Node: node,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -192,7 +193,7 @@ func TestClientEndpoint_CreateNodeEvals(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Inject fake evaluations
alloc := mockAlloc()
alloc := mock.Alloc()
state := s1.fsm.State()
err := state.UpdateAllocations(1, nil, []*structs.Allocation{alloc})
if err != nil {

View File

@@ -4,6 +4,7 @@ import (
"testing"
"time"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -29,7 +30,7 @@ func TestEvalBroker_Enqueue_Dequeue_Nack_Ack(t *testing.T) {
b := testBroker(t, 0)
// Enqueue, but broker is disabled!
eval := mockEval()
eval := mock.Eval()
err := b.Enqueue(eval)
if err != nil {
t.Fatalf("err: %v", err)
@@ -167,13 +168,13 @@ func TestEvalBroker_Serialize_DuplicateJobID(t *testing.T) {
b := testBroker(t, 0)
b.SetEnabled(true)
eval := mockEval()
eval := mock.Eval()
err := b.Enqueue(eval)
if err != nil {
t.Fatalf("err: %v", err)
}
eval2 := mockEval()
eval2 := mock.Eval()
eval2.JobID = eval.JobID
eval2.CreateIndex = eval.CreateIndex + 1
err = b.Enqueue(eval2)
@@ -181,7 +182,7 @@ func TestEvalBroker_Serialize_DuplicateJobID(t *testing.T) {
t.Fatalf("err: %v", err)
}
eval3 := mockEval()
eval3 := mock.Eval()
eval3.JobID = eval.JobID
eval3.CreateIndex = eval.CreateIndex + 2
err = b.Enqueue(eval3)
@@ -319,7 +320,7 @@ func TestEvalBroker_Enqueue_Disable(t *testing.T) {
b := testBroker(t, 0)
// Enqueue
eval := mockEval()
eval := mock.Eval()
b.SetEnabled(true)
err := b.Enqueue(eval)
if err != nil {
@@ -367,15 +368,15 @@ func TestEvalBroker_Dequeue_Priority(t *testing.T) {
b := testBroker(t, 0)
b.SetEnabled(true)
eval1 := mockEval()
eval1 := mock.Eval()
eval1.Priority = 10
b.Enqueue(eval1)
eval2 := mockEval()
eval2 := mock.Eval()
eval2.Priority = 30
b.Enqueue(eval2)
eval3 := mockEval()
eval3 := mock.Eval()
eval3.Priority = 20
b.Enqueue(eval3)
@@ -402,7 +403,7 @@ func TestEvalBroker_Dequeue_FIFO(t *testing.T) {
NUM := 100
for i := 0; i < NUM; i++ {
eval1 := mockEval()
eval1 := mock.Eval()
eval1.CreateIndex = uint64(i)
eval1.ModifyIndex = uint64(i)
b.Enqueue(eval1)
@@ -423,7 +424,7 @@ func TestEvalBroker_Dequeue_Fairness(t *testing.T) {
NUM := 100
for i := 0; i < NUM; i++ {
eval1 := mockEval()
eval1 := mock.Eval()
if i < (NUM / 2) {
eval1.Type = structs.JobTypeService
} else {
@@ -481,7 +482,7 @@ func TestEvalBroker_Dequeue_Blocked(t *testing.T) {
time.Sleep(5 * time.Millisecond)
// Enqueue
eval := mockEval()
eval := mock.Eval()
err := b.Enqueue(eval)
if err != nil {
t.Fatalf("err: %v", err)
@@ -504,7 +505,7 @@ func TestEvalBroker_Nack_Timeout(t *testing.T) {
b.SetEnabled(true)
// Enqueue
eval := mockEval()
eval := mock.Eval()
err := b.Enqueue(eval)
if err != nil {
t.Fatalf("err: %v", err)

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/hashicorp/net-rpc-msgpackrpc"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -17,7 +18,7 @@ func TestEvalEndpoint_GetEval(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
eval1 := mockEval()
eval1 := mock.Eval()
s1.fsm.State().UpsertEvals(1000, []*structs.Evaluation{eval1})
// Lookup the eval
@@ -59,7 +60,7 @@ func TestEvalEndpoint_Dequeue(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
eval1 := mockEval()
eval1 := mock.Eval()
s1.evalBroker.Enqueue(eval1)
// Dequeue the eval
@@ -94,7 +95,7 @@ func TestEvalEndpoint_Ack(t *testing.T) {
})
// Create the register request
eval1 := mockEval()
eval1 := mock.Eval()
s1.evalBroker.Enqueue(eval1)
out, err := s1.evalBroker.Dequeue(defaultSched, time.Second)
if err != nil {
@@ -132,7 +133,7 @@ func TestEvalEndpoint_Nack(t *testing.T) {
})
// Create the register request
eval1 := mockEval()
eval1 := mock.Eval()
s1.evalBroker.Enqueue(eval1)
out, _ := s1.evalBroker.Dequeue(defaultSched, time.Second)
if out == nil {

View File

@@ -8,6 +8,7 @@ import (
"github.com/armon/go-metrics"
"github.com/hashicorp/go-msgpack/codec"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/raft"
)
@@ -38,14 +39,14 @@ type nomadFSM struct {
evalBroker *EvalBroker
logOutput io.Writer
logger *log.Logger
state *StateStore
state *state.StateStore
}
// nomadSnapshot is used to provide a snapshot of the current
// state in a way that can be accessed concurrently with operations
// that may modify the live state.
type nomadSnapshot struct {
snap *StateSnapshot
snap *state.StateSnapshot
}
// snapshotHeader is the first entry in our snapshot
@@ -55,7 +56,7 @@ type snapshotHeader struct {
// NewFSMPath is used to construct a new FSM with a blank state
func NewFSM(evalBroker *EvalBroker, logOutput io.Writer) (*nomadFSM, error) {
// Create a state store
state, err := NewStateStore(logOutput)
state, err := state.NewStateStore(logOutput)
if err != nil {
return nil, err
}
@@ -75,7 +76,7 @@ func (n *nomadFSM) Close() error {
}
// State is used to return a handle to the current state
func (n *nomadFSM) State() *StateStore {
func (n *nomadFSM) State() *state.StateStore {
return n.state
}
@@ -253,14 +254,14 @@ func (n *nomadFSM) Restore(old io.ReadCloser) error {
defer old.Close()
// Create a new state store
state, err := NewStateStore(n.logOutput)
newState, err := state.NewStateStore(n.logOutput)
if err != nil {
return err
}
n.state = state
n.state = newState
// Start the state restore
restore, err := state.Restore()
restore, err := newState.Restore()
if err != nil {
return err
}
@@ -325,7 +326,7 @@ func (n *nomadFSM) Restore(old io.ReadCloser) error {
}
case IndexSnapshot:
idx := new(IndexEntry)
idx := new(state.IndexEntry)
if err := dec.Decode(idx); err != nil {
return err
}
@@ -395,7 +396,7 @@ func (s *nomadSnapshot) persistIndexes(sink raft.SnapshotSink,
}
// Prepare the request struct
idx := raw.(*IndexEntry)
idx := raw.(*state.IndexEntry)
// Write out a node registration
sink.Write([]byte{byte(IndexSnapshot)})

View File

@@ -6,6 +6,8 @@ import (
"reflect"
"testing"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/raft"
)
@@ -28,6 +30,17 @@ func (m *MockSink) Close() error {
return nil
}
func testStateStore(t *testing.T) *state.StateStore {
state, err := state.NewStateStore(os.Stderr)
if err != nil {
t.Fatalf("err: %v", err)
}
if state == nil {
t.Fatalf("missing state")
}
return state
}
func testFSM(t *testing.T) *nomadFSM {
fsm, err := NewFSM(testBroker(t, 0), os.Stderr)
if err != nil {
@@ -52,7 +65,7 @@ func TestFSM_RegisterNode(t *testing.T) {
fsm := testFSM(t)
req := structs.NodeRegisterRequest{
Node: mockNode(),
Node: mock.Node(),
}
buf, err := structs.Encode(structs.NodeRegisterRequestType, req)
if err != nil {
@@ -80,7 +93,7 @@ func TestFSM_RegisterNode(t *testing.T) {
func TestFSM_DeregisterNode(t *testing.T) {
fsm := testFSM(t)
node := mockNode()
node := mock.Node()
req := structs.NodeRegisterRequest{
Node: node,
}
@@ -120,7 +133,7 @@ func TestFSM_DeregisterNode(t *testing.T) {
func TestFSM_UpdateNodeStatus(t *testing.T) {
fsm := testFSM(t)
node := mockNode()
node := mock.Node()
req := structs.NodeRegisterRequest{
Node: node,
}
@@ -162,7 +175,7 @@ func TestFSM_RegisterJob(t *testing.T) {
fsm := testFSM(t)
req := structs.JobRegisterRequest{
Job: mockJob(),
Job: mock.Job(),
}
buf, err := structs.Encode(structs.JobRegisterRequestType, req)
if err != nil {
@@ -190,7 +203,7 @@ func TestFSM_RegisterJob(t *testing.T) {
func TestFSM_DeregisterJob(t *testing.T) {
fsm := testFSM(t)
job := mockJob()
job := mock.Job()
req := structs.JobRegisterRequest{
Job: job,
}
@@ -232,7 +245,7 @@ func TestFSM_UpdateEval(t *testing.T) {
fsm.evalBroker.SetEnabled(true)
req := structs.EvalUpdateRequest{
Evals: []*structs.Evaluation{mockEval()},
Evals: []*structs.Evaluation{mock.Eval()},
}
buf, err := structs.Encode(structs.EvalUpdateRequestType, req)
if err != nil {
@@ -266,7 +279,7 @@ func TestFSM_UpdateEval(t *testing.T) {
func TestFSM_DeleteEval(t *testing.T) {
fsm := testFSM(t)
eval := mockEval()
eval := mock.Eval()
req := structs.EvalUpdateRequest{
Evals: []*structs.Evaluation{eval},
}
@@ -306,7 +319,7 @@ func TestFSM_DeleteEval(t *testing.T) {
func TestFSM_UpdateAllocations(t *testing.T) {
fsm := testFSM(t)
alloc := mockAlloc()
alloc := mock.Alloc()
req := structs.AllocUpdateRequest{
Evict: nil,
Alloc: []*structs.Allocation{alloc},
@@ -384,9 +397,9 @@ func TestFSM_SnapshotRestore_Nodes(t *testing.T) {
// Add some state
fsm := testFSM(t)
state := fsm.State()
node1 := mockNode()
node1 := mock.Node()
state.RegisterNode(1000, node1)
node2 := mockNode()
node2 := mock.Node()
state.RegisterNode(1001, node2)
// Verify the contents
@@ -406,9 +419,9 @@ func TestFSM_SnapshotRestore_Jobs(t *testing.T) {
// Add some state
fsm := testFSM(t)
state := fsm.State()
job1 := mockJob()
job1 := mock.Job()
state.RegisterJob(1000, job1)
job2 := mockJob()
job2 := mock.Job()
state.RegisterJob(1001, job2)
// Verify the contents
@@ -428,9 +441,9 @@ func TestFSM_SnapshotRestore_Evals(t *testing.T) {
// Add some state
fsm := testFSM(t)
state := fsm.State()
eval1 := mockEval()
eval1 := mock.Eval()
state.UpsertEvals(1000, []*structs.Evaluation{eval1})
eval2 := mockEval()
eval2 := mock.Eval()
state.UpsertEvals(1001, []*structs.Evaluation{eval2})
// Verify the contents
@@ -450,9 +463,9 @@ func TestFSM_SnapshotRestore_Allocs(t *testing.T) {
// Add some state
fsm := testFSM(t)
state := fsm.State()
alloc1 := mockAlloc()
alloc1 := mock.Alloc()
state.UpdateAllocations(1000, nil, []*structs.Allocation{alloc1})
alloc2 := mockAlloc()
alloc2 := mock.Alloc()
state.UpdateAllocations(1001, nil, []*structs.Allocation{alloc2})
// Verify the contents
@@ -472,7 +485,7 @@ func TestFSM_SnapshotRestore_Indexes(t *testing.T) {
// Add some state
fsm := testFSM(t)
state := fsm.State()
node1 := mockNode()
node1 := mock.Node()
state.RegisterNode(1000, node1)
// Verify the contents

View File

@@ -5,6 +5,7 @@ import (
"testing"
"github.com/hashicorp/net-rpc-msgpackrpc"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -16,7 +17,7 @@ func TestJobEndpoint_Register(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
job := mockJob()
job := mock.Job()
req := &structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -83,7 +84,7 @@ func TestJobEndpoint_Register_Existing(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
job := mockJob()
job := mock.Job()
req := &structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -99,7 +100,7 @@ func TestJobEndpoint_Register_Existing(t *testing.T) {
}
// Update the job definition
job2 := mockJob()
job2 := mock.Job()
job2.Priority = 100
job2.ID = job.ID
req.Job = job2
@@ -167,7 +168,7 @@ func TestJobEndpoint_Deregister(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
job := mockJob()
job := mock.Job()
reg := &structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "region1"},
@@ -241,7 +242,7 @@ func TestJobEndpoint_GetJob(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the register request
job := mockJob()
job := mock.Job()
reg := &structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "region1"},

View File

@@ -6,6 +6,7 @@ import (
"testing"
"time"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -250,7 +251,7 @@ func TestLeader_EvalBroker_Reset(t *testing.T) {
// Inject a pending eval
req := structs.EvalUpdateRequest{
Evals: []*structs.Evaluation{mockEval()},
Evals: []*structs.Evaluation{mock.Eval()},
}
_, _, err := leader.raftApply(structs.EvalUpdateRequestType, req)
if err != nil {

157
nomad/mock/mock.go Normal file
View File

@@ -0,0 +1,157 @@
package mock
import (
crand "crypto/rand"
"fmt"
"github.com/hashicorp/nomad/nomad/structs"
)
func GenerateUUID() string {
buf := make([]byte, 16)
if _, err := crand.Read(buf); err != nil {
panic(fmt.Errorf("failed to read random bytes: %v", err))
}
return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x",
buf[0:4],
buf[4:6],
buf[6:8],
buf[8:10],
buf[10:16])
}
func Node() *structs.Node {
node := &structs.Node{
ID: GenerateUUID(),
Datacenter: "dc1",
Name: "foobar",
Attributes: map[string]string{
"os": "linux",
"arch": "x86",
"version": "0.1.0",
"driver.docker": "1.0.0",
},
Resources: &structs.Resources{
CPU: 4.0,
MemoryMB: 8192,
DiskMB: 100 * 1024,
IOPS: 150,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
Public: true,
CIDR: "192.168.0.100/32",
ReservedPorts: []int{22},
MBits: 1000,
},
},
},
Reserved: &structs.Resources{
CPU: 0.1,
MemoryMB: 256,
DiskMB: 4 * 1024,
},
Links: map[string]string{
"consul": "foobar.dc1",
},
Meta: map[string]string{
"pci-dss": "true",
},
NodeClass: "linux-medium-pci",
Status: structs.NodeStatusReady,
}
return node
}
func Job() *structs.Job {
job := &structs.Job{
ID: GenerateUUID(),
Name: "my-job",
Type: structs.JobTypeService,
Priority: 50,
AllAtOnce: false,
Constraints: []*structs.Constraint{
&structs.Constraint{
Hard: true,
LTarget: "attr.os",
RTarget: "linux",
Operand: "=",
},
},
TaskGroups: []*structs.TaskGroup{
&structs.TaskGroup{
Name: "web",
Count: 10,
Tasks: []*structs.Task{
&structs.Task{
Name: "web",
Driver: "docker",
Config: map[string]string{
"image": "hashicorp/web",
"version": "v1.2.3",
},
Resources: &structs.Resources{
CPU: 0.5,
MemoryMB: 256,
},
},
},
Meta: map[string]string{
"elb_check_type": "http",
"elb_check_interval": "30s",
"elb_check_min": "3",
},
},
},
Meta: map[string]string{
"owner": "armon",
},
Status: structs.JobStatusPending,
}
return job
}
func Eval() *structs.Evaluation {
eval := &structs.Evaluation{
ID: GenerateUUID(),
Priority: 50,
Type: structs.JobTypeService,
JobID: GenerateUUID(),
Status: structs.EvalStatusPending,
}
return eval
}
func Alloc() *structs.Allocation {
alloc := &structs.Allocation{
ID: GenerateUUID(),
NodeID: "foo",
Resources: &structs.Resources{
CPU: 1.0,
MemoryMB: 1024,
DiskMB: 1024,
IOPS: 10,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
Public: true,
CIDR: "192.168.0.100/32",
ReservedPorts: []int{12345},
MBits: 100,
},
},
},
Job: Job(),
}
alloc.JobID = alloc.Job.ID
return alloc
}
func Plan() *structs.Plan {
return &structs.Plan{
Priority: 50,
}
}
func PlanResult() *structs.PlanResult {
return &structs.PlanResult{}
}

View File

@@ -5,6 +5,7 @@ import (
"time"
"github.com/armon/go-metrics"
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -69,7 +70,7 @@ func (s *Server) applyPlan(result *structs.PlanResult) (uint64, error) {
// evaluatePlan is used to determine what portions of a plan
// can be applied if any. Returns if there should be a plan application
// which may be partial or if there was an error
func evaluatePlan(snap *StateSnapshot, plan *structs.Plan) (*structs.PlanResult, error) {
func evaluatePlan(snap *state.StateSnapshot, plan *structs.Plan) (*structs.PlanResult, error) {
defer metrics.MeasureSince([]string{"nomad", "plan", "evaluate"}, time.Now())
// Create a result holder for the plan
@@ -123,7 +124,7 @@ func evaluatePlan(snap *StateSnapshot, plan *structs.Plan) (*structs.PlanResult,
// evaluateNodePlan is used to evalute the plan for a single node,
// returning if the plan is valid or if an error is encountered
func evaluateNodePlan(snap *StateSnapshot, plan *structs.Plan, nodeID string) (bool, error) {
func evaluateNodePlan(snap *state.StateSnapshot, plan *structs.Plan, nodeID string) (bool, error) {
// If this is an evict-only plan, it always 'fits' since we are removing things.
if len(plan.NodeAllocation[nodeID]) == 0 {
return true, nil

View File

@@ -3,6 +3,7 @@ package nomad
import (
"testing"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -30,11 +31,11 @@ func TestPlanApply_applyPlan(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Register ndoe
node := mockNode()
node := mock.Node()
testRegisterNode(t, s1, node)
// Register alloc
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.PlanResult{
NodeEvict: map[string][]string{
node.ID: []string{},
@@ -63,7 +64,7 @@ func TestPlanApply_applyPlan(t *testing.T) {
}
// Evict alloc, Register alloc2
alloc2 := mockAlloc()
alloc2 := mock.Alloc()
plan = &structs.PlanResult{
NodeEvict: map[string][]string{
node.ID: []string{alloc.ID},
@@ -103,11 +104,11 @@ func TestPlanApply_applyPlan(t *testing.T) {
func TestPlanApply_EvalPlan_Simple(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
state.RegisterNode(1000, node)
snap, _ := state.Snapshot()
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
node.ID: []*structs.Allocation{alloc},
@@ -125,14 +126,14 @@ func TestPlanApply_EvalPlan_Simple(t *testing.T) {
func TestPlanApply_EvalPlan_Partial(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
state.RegisterNode(1000, node)
node2 := mockNode()
node2 := mock.Node()
state.RegisterNode(1001, node2)
snap, _ := state.Snapshot()
alloc := mockAlloc()
alloc2 := mockAlloc() // Ensure alloc2 does not fit
alloc := mock.Alloc()
alloc2 := mock.Alloc() // Ensure alloc2 does not fit
alloc2.Resources = node2.Resources
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
@@ -159,14 +160,14 @@ func TestPlanApply_EvalPlan_Partial(t *testing.T) {
func TestPlanApply_EvalPlan_Partial_AllAtOnce(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
state.RegisterNode(1000, node)
node2 := mockNode()
node2 := mock.Node()
state.RegisterNode(1001, node2)
snap, _ := state.Snapshot()
alloc := mockAlloc()
alloc2 := mockAlloc() // Ensure alloc2 does not fit
alloc := mock.Alloc()
alloc2 := mock.Alloc() // Ensure alloc2 does not fit
alloc2.Resources = node2.Resources
plan := &structs.Plan{
AllAtOnce: true, // Require all to make progress
@@ -191,11 +192,11 @@ func TestPlanApply_EvalPlan_Partial_AllAtOnce(t *testing.T) {
func TestPlanApply_EvalNodePlan_Simple(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
state.RegisterNode(1000, node)
snap, _ := state.Snapshot()
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
node.ID: []*structs.Allocation{alloc},
@@ -213,12 +214,12 @@ func TestPlanApply_EvalNodePlan_Simple(t *testing.T) {
func TestPlanApply_EvalNodePlan_NodeNotReady(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
node.Status = structs.NodeStatusInit
state.RegisterNode(1000, node)
snap, _ := state.Snapshot()
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
node.ID: []*structs.Allocation{alloc},
@@ -239,7 +240,7 @@ func TestPlanApply_EvalNodePlan_NodeNotExist(t *testing.T) {
snap, _ := state.Snapshot()
nodeID := "foo"
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
nodeID: []*structs.Allocation{alloc},
@@ -256,9 +257,9 @@ func TestPlanApply_EvalNodePlan_NodeNotExist(t *testing.T) {
}
func TestPlanApply_EvalNodePlan_NodeFull(t *testing.T) {
alloc := mockAlloc()
alloc := mock.Alloc()
state := testStateStore(t)
node := mockNode()
node := mock.Node()
alloc.NodeID = node.ID
node.Resources = alloc.Resources
node.Reserved = nil
@@ -283,9 +284,9 @@ func TestPlanApply_EvalNodePlan_NodeFull(t *testing.T) {
}
func TestPlanApply_EvalNodePlan_NodeFull_Evict(t *testing.T) {
alloc := mockAlloc()
alloc := mock.Alloc()
state := testStateStore(t)
node := mockNode()
node := mock.Node()
alloc.NodeID = node.ID
node.Resources = alloc.Resources
node.Reserved = nil
@@ -294,7 +295,7 @@ func TestPlanApply_EvalNodePlan_NodeFull_Evict(t *testing.T) {
[]*structs.Allocation{alloc})
snap, _ := state.Snapshot()
alloc2 := mockAlloc()
alloc2 := mock.Alloc()
plan := &structs.Plan{
NodeEvict: map[string][]string{
node.ID: []string{alloc.ID},
@@ -314,9 +315,9 @@ func TestPlanApply_EvalNodePlan_NodeFull_Evict(t *testing.T) {
}
func TestPlanApply_EvalNodePlan_NodeMaint_EvictOnly(t *testing.T) {
alloc := mockAlloc()
alloc := mock.Alloc()
state := testStateStore(t)
node := mockNode()
node := mock.Node()
alloc.NodeID = node.ID
node.Resources = alloc.Resources
node.Reserved = nil

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/hashicorp/net-rpc-msgpackrpc"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
)
@@ -15,7 +16,7 @@ func TestPlanEndpoint_Submit(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Submit a plan
plan := mockPlan()
plan := mock.Plan()
req := &structs.PlanRequest{
Plan: plan,
WriteRequest: structs.WriteRequest{Region: "region1"},

View File

@@ -4,6 +4,7 @@ import (
"testing"
"time"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -15,16 +16,6 @@ func testPlanQueue(t *testing.T) *PlanQueue {
return pq
}
func mockPlan() *structs.Plan {
return &structs.Plan{
Priority: 50,
}
}
func mockPlanResult() *structs.PlanResult {
return &structs.PlanResult{}
}
func TestPlanQueue_Enqueue_Dequeue(t *testing.T) {
pq := testPlanQueue(t)
if pq.Enabled() {
@@ -35,7 +26,7 @@ func TestPlanQueue_Enqueue_Dequeue(t *testing.T) {
t.Fatalf("should be enabled")
}
plan := mockPlan()
plan := mock.Plan()
future, err := pq.Enqueue(plan)
if err != nil {
t.Fatalf("err: %v", err)
@@ -69,7 +60,7 @@ func TestPlanQueue_Enqueue_Dequeue(t *testing.T) {
t.Fatalf("bad: %#v", pending)
}
result := mockPlanResult()
result := mock.PlanResult()
pending.respond(result, nil)
select {
@@ -86,7 +77,7 @@ func TestPlanQueue_Enqueue_Disable(t *testing.T) {
pq := testPlanQueue(t)
// Enqueue
plan := mockPlan()
plan := mock.Plan()
pq.SetEnabled(true)
future, err := pq.Enqueue(plan)
if err != nil {
@@ -137,15 +128,15 @@ func TestPlanQueue_Dequeue_Priority(t *testing.T) {
pq := testPlanQueue(t)
pq.SetEnabled(true)
plan1 := mockPlan()
plan1 := mock.Plan()
plan1.Priority = 10
pq.Enqueue(plan1)
plan2 := mockPlan()
plan2 := mock.Plan()
plan2.Priority = 30
pq.Enqueue(plan2)
plan3 := mockPlan()
plan3 := mock.Plan()
plan3.Priority = 20
pq.Enqueue(plan3)
@@ -173,7 +164,7 @@ func TestPlanQueue_Dequeue_FIFO(t *testing.T) {
plans := make([]*structs.Plan, NUM)
for i := 0; i < NUM; i++ {
plan := mockPlan()
plan := mock.Plan()
pq.Enqueue(plan)
plans[i] = plan
}

View File

@@ -1,4 +1,4 @@
package nomad
package state
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package nomad
package state
import (
"testing"

View File

@@ -1,4 +1,4 @@
package nomad
package state
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package nomad
package state
import (
"os"
@@ -6,6 +6,7 @@ import (
"sort"
"testing"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -20,134 +21,9 @@ func testStateStore(t *testing.T) *StateStore {
return state
}
func mockNode() *structs.Node {
node := &structs.Node{
ID: generateUUID(),
Datacenter: "dc1",
Name: "foobar",
Attributes: map[string]string{
"os": "linux",
"arch": "x86",
"version": "0.1.0",
"driver.docker": "1.0.0",
},
Resources: &structs.Resources{
CPU: 4.0,
MemoryMB: 8192,
DiskMB: 100 * 1024,
IOPS: 150,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
Public: true,
CIDR: "192.168.0.100/32",
ReservedPorts: []int{22},
MBits: 1000,
},
},
},
Reserved: &structs.Resources{
CPU: 0.1,
MemoryMB: 256,
DiskMB: 4 * 1024,
},
Links: map[string]string{
"consul": "foobar.dc1",
},
Meta: map[string]string{
"pci-dss": "true",
},
NodeClass: "linux-medium-pci",
Status: structs.NodeStatusReady,
}
return node
}
func mockJob() *structs.Job {
job := &structs.Job{
ID: generateUUID(),
Name: "my-job",
Type: structs.JobTypeService,
Priority: 50,
AllAtOnce: false,
Constraints: []*structs.Constraint{
&structs.Constraint{
Hard: true,
LTarget: "attr.os",
RTarget: "linux",
Operand: "=",
},
},
TaskGroups: []*structs.TaskGroup{
&structs.TaskGroup{
Name: "web",
Count: 10,
Tasks: []*structs.Task{
&structs.Task{
Name: "web",
Driver: "docker",
Config: map[string]string{
"image": "hashicorp/web",
"version": "v1.2.3",
},
Resources: &structs.Resources{
CPU: 0.5,
MemoryMB: 256,
},
},
},
Meta: map[string]string{
"elb_check_type": "http",
"elb_check_interval": "30s",
"elb_check_min": "3",
},
},
},
Meta: map[string]string{
"owner": "armon",
},
Status: structs.JobStatusPending,
}
return job
}
func mockEval() *structs.Evaluation {
eval := &structs.Evaluation{
ID: generateUUID(),
Priority: 50,
Type: structs.JobTypeService,
JobID: generateUUID(),
Status: structs.EvalStatusPending,
}
return eval
}
func mockAlloc() *structs.Allocation {
alloc := &structs.Allocation{
ID: generateUUID(),
NodeID: "foo",
Resources: &structs.Resources{
CPU: 1.0,
MemoryMB: 1024,
DiskMB: 1024,
IOPS: 10,
Networks: []*structs.NetworkResource{
&structs.NetworkResource{
Public: true,
CIDR: "192.168.0.100/32",
ReservedPorts: []int{12345},
MBits: 100,
},
},
},
Job: mockJob(),
}
alloc.JobID = alloc.Job.ID
return alloc
}
func TestStateStore_RegisterNode_GetNode(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
err := state.RegisterNode(1000, node)
if err != nil {
@@ -174,7 +50,7 @@ func TestStateStore_RegisterNode_GetNode(t *testing.T) {
func TestStateStore_DeregisterNode_GetNode(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
err := state.RegisterNode(1000, node)
if err != nil {
@@ -206,7 +82,7 @@ func TestStateStore_DeregisterNode_GetNode(t *testing.T) {
func TestStateStore_UpdateNode_GetNode(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
err := state.RegisterNode(1000, node)
if err != nil {
@@ -244,7 +120,7 @@ func TestStateStore_Nodes(t *testing.T) {
var nodes []*structs.Node
for i := 0; i < 10; i++ {
node := mockNode()
node := mock.Node()
nodes = append(nodes, node)
err := state.RegisterNode(1000+uint64(i), node)
@@ -283,7 +159,7 @@ func TestStateStore_RestoreNode(t *testing.T) {
t.Fatalf("err: %v", err)
}
node := mockNode()
node := mock.Node()
err = restore.NodeRestore(node)
if err != nil {
t.Fatalf("err: %v", err)
@@ -303,7 +179,7 @@ func TestStateStore_RestoreNode(t *testing.T) {
func TestStateStore_RegisterJob_GetJob(t *testing.T) {
state := testStateStore(t)
job := mockJob()
job := mock.Job()
err := state.RegisterJob(1000, job)
if err != nil {
@@ -330,14 +206,14 @@ func TestStateStore_RegisterJob_GetJob(t *testing.T) {
func TestStateStore_UpdateRegisterJob_GetJob(t *testing.T) {
state := testStateStore(t)
job := mockJob()
job := mock.Job()
err := state.RegisterJob(1000, job)
if err != nil {
t.Fatalf("err: %v", err)
}
job2 := mockJob()
job2 := mock.Job()
job2.ID = job.ID
err = state.RegisterJob(1001, job2)
if err != nil {
@@ -371,7 +247,7 @@ func TestStateStore_UpdateRegisterJob_GetJob(t *testing.T) {
func TestStateStore_DeregisterJob_GetJob(t *testing.T) {
state := testStateStore(t)
job := mockJob()
job := mock.Job()
err := state.RegisterJob(1000, job)
if err != nil {
@@ -406,7 +282,7 @@ func TestStateStore_Jobs(t *testing.T) {
var jobs []*structs.Job
for i := 0; i < 10; i++ {
job := mockJob()
job := mock.Job()
jobs = append(jobs, job)
err := state.RegisterJob(1000+uint64(i), job)
@@ -445,7 +321,7 @@ func TestStateStore_RestoreJob(t *testing.T) {
t.Fatalf("err: %v", err)
}
job := mockJob()
job := mock.Job()
err = restore.JobRestore(job)
if err != nil {
t.Fatalf("err: %v", err)
@@ -465,7 +341,7 @@ func TestStateStore_RestoreJob(t *testing.T) {
func TestStateStore_Indexes(t *testing.T) {
state := testStateStore(t)
node := mockNode()
node := mock.Node()
err := state.RegisterNode(1000, node)
if err != nil {
@@ -523,7 +399,7 @@ func TestStateStore_RestoreIndex(t *testing.T) {
func TestStateStore_UpsertEvals_GetEval(t *testing.T) {
state := testStateStore(t)
eval := mockEval()
eval := mock.Eval()
err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
if err != nil {
@@ -550,14 +426,14 @@ func TestStateStore_UpsertEvals_GetEval(t *testing.T) {
func TestStateStore_Update_UpsertEvals_GetEval(t *testing.T) {
state := testStateStore(t)
eval := mockEval()
eval := mock.Eval()
err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
if err != nil {
t.Fatalf("err: %v", err)
}
eval2 := mockEval()
eval2 := mock.Eval()
eval2.ID = eval.ID
err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
if err != nil {
@@ -591,7 +467,7 @@ func TestStateStore_Update_UpsertEvals_GetEval(t *testing.T) {
func TestStateStore_DeleteEval_GetEval(t *testing.T) {
state := testStateStore(t)
eval := mockEval()
eval := mock.Eval()
err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
if err != nil {
@@ -626,7 +502,7 @@ func TestStateStore_Evals(t *testing.T) {
var evals []*structs.Evaluation
for i := 0; i < 10; i++ {
eval := mockEval()
eval := mock.Eval()
evals = append(evals, eval)
err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
@@ -665,7 +541,7 @@ func TestStateStore_RestoreEval(t *testing.T) {
t.Fatalf("err: %v", err)
}
job := mockEval()
job := mock.Eval()
err = restore.EvalRestore(job)
if err != nil {
t.Fatalf("err: %v", err)
@@ -686,7 +562,7 @@ func TestStateStore_RestoreEval(t *testing.T) {
func TestStateStore_UpsertAlloc_GetAlloc(t *testing.T) {
state := testStateStore(t)
alloc := mockAlloc()
alloc := mock.Alloc()
err := state.UpdateAllocations(1000, nil,
[]*structs.Allocation{alloc})
if err != nil {
@@ -713,7 +589,7 @@ func TestStateStore_UpsertAlloc_GetAlloc(t *testing.T) {
func TestStateStore_UpdateAlloc_GetAlloc(t *testing.T) {
state := testStateStore(t)
alloc := mockAlloc()
alloc := mock.Alloc()
err := state.UpdateAllocations(1000, nil,
[]*structs.Allocation{alloc})
@@ -721,7 +597,7 @@ func TestStateStore_UpdateAlloc_GetAlloc(t *testing.T) {
t.Fatalf("err: %v", err)
}
alloc2 := mockAlloc()
alloc2 := mock.Alloc()
alloc2.ID = alloc.ID
alloc2.NodeID = alloc.NodeID + ".new"
err = state.UpdateAllocations(1001, nil,
@@ -757,7 +633,7 @@ func TestStateStore_UpdateAlloc_GetAlloc(t *testing.T) {
func TestStateStore_EvictAlloc_GetAlloc(t *testing.T) {
state := testStateStore(t)
alloc := mockAlloc()
alloc := mock.Alloc()
err := state.UpdateAllocations(1001, nil, []*structs.Allocation{alloc})
if err != nil {
@@ -792,7 +668,7 @@ func TestStateStore_AllocsByNode(t *testing.T) {
var allocs []*structs.Allocation
for i := 0; i < 10; i++ {
alloc := mockAlloc()
alloc := mock.Alloc()
alloc.NodeID = "foo"
allocs = append(allocs, alloc)
}
@@ -820,7 +696,7 @@ func TestStateStore_AllocsByJob(t *testing.T) {
var allocs []*structs.Allocation
for i := 0; i < 10; i++ {
alloc := mockAlloc()
alloc := mock.Alloc()
alloc.JobID = "foo"
allocs = append(allocs, alloc)
}
@@ -848,7 +724,7 @@ func TestStateStore_Allocs(t *testing.T) {
var allocs []*structs.Allocation
for i := 0; i < 10; i++ {
alloc := mockAlloc()
alloc := mock.Alloc()
allocs = append(allocs, alloc)
}
@@ -887,7 +763,7 @@ func TestStateStore_RestoreAlloc(t *testing.T) {
t.Fatalf("err: %v", err)
}
alloc := mockAlloc()
alloc := mock.Alloc()
err = restore.AllocRestore(alloc)
if err != nil {
t.Fatalf("err: %v", err)

View File

@@ -1,6 +1,7 @@
package nomad
import (
"github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/scheduler"
)
@@ -10,11 +11,11 @@ import (
// across the cluster.
type SystemScheduler struct {
srv *Server
snap *StateSnapshot
snap *state.StateSnapshot
}
// NewSystemScheduler is used to return a new system scheduler instance
func NewSystemScheduler(srv *Server, snap *StateSnapshot) scheduler.Scheduler {
func NewSystemScheduler(srv *Server, snap *state.StateSnapshot) scheduler.Scheduler {
s := &SystemScheduler{
srv: srv,
snap: snap,

View File

@@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/scheduler"
"github.com/hashicorp/nomad/testutil"
@@ -49,7 +50,7 @@ func TestWorker_dequeueEvaluation(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the evaluation
eval1 := mockEval()
eval1 := mock.Eval()
s1.evalBroker.Enqueue(eval1)
// Create a worker
@@ -104,7 +105,7 @@ func TestWorker_sendAck(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Create the evaluation
eval1 := mockEval()
eval1 := mock.Eval()
s1.evalBroker.Enqueue(eval1)
// Create a worker
@@ -180,7 +181,7 @@ func TestWorker_invokeScheduler(t *testing.T) {
defer s1.Shutdown()
w := &Worker{srv: s1, logger: s1.logger}
eval := mockEval()
eval := mock.Eval()
eval.Type = "noop"
err := w.invokeScheduler(eval)
@@ -198,11 +199,11 @@ func TestWorker_SubmitPlan(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Register node
node := mockNode()
node := mock.Node()
testRegisterNode(t, s1, node)
// Create an allocation plan
alloc := mockAlloc()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
node.ID: []*structs.Allocation{alloc},
@@ -243,12 +244,12 @@ func TestWorker_SubmitPlan_MissingNodeRefresh(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
// Register node
node := mockNode()
node := mock.Node()
testRegisterNode(t, s1, node)
// Create an allocation plan, with unregistered node
node2 := mockNode()
alloc := mockAlloc()
node2 := mock.Node()
alloc := mock.Alloc()
plan := &structs.Plan{
NodeAllocation: map[string][]*structs.Allocation{
node2.ID: []*structs.Allocation{alloc},