From b7088b3d402fd556010ca52e4955ce7fe65ab873 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Thu, 6 Jul 2017 09:28:08 -0700 Subject: [PATCH] plan apply tests --- nomad/plan_apply.go | 1 - nomad/plan_apply_test.go | 83 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/nomad/plan_apply.go b/nomad/plan_apply.go index a300126f4..1035d70ab 100644 --- a/nomad/plan_apply.go +++ b/nomad/plan_apply.go @@ -328,7 +328,6 @@ OUTER: return result, mErr.ErrorOrNil() } -// TODO test // correctDeploymentCanaries ensures that the deployment object doesn't list any // canaries as placed if they didn't actually get placed. This could happen if // the plan had a partial commit. diff --git a/nomad/plan_apply_test.go b/nomad/plan_apply_test.go index b4b16bbac..d202eaab6 100644 --- a/nomad/plan_apply_test.go +++ b/nomad/plan_apply_test.go @@ -67,13 +67,34 @@ func TestPlanApply_applyPlan(t *testing.T) { node := mock.Node() testRegisterNode(t, s1, node) - // Register alloc + // Register a fake deployment + oldDeployment := mock.Deployment() + if err := s1.State().UpsertDeployment(900, oldDeployment); err != nil { + t.Fatalf("UpsertDeployment failed: %v", err) + } + + // Create a deployment + dnew := mock.Deployment() + + // Create a deployment update for the old deployment id + desiredStatus, desiredStatusDescription := "foo", "bar" + updates := []*structs.DeploymentStatusUpdate{ + { + DeploymentID: oldDeployment.ID, + Status: desiredStatus, + StatusDescription: desiredStatusDescription, + }, + } + + // Register alloc, deployment and deployment update alloc := mock.Alloc() s1.State().UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)) planRes := &structs.PlanResult{ NodeAllocation: map[string][]*structs.Allocation{ node.ID: []*structs.Allocation{alloc}, }, + Deployment: dnew, + DeploymentUpdates: updates, } // Snapshot the state @@ -84,8 +105,9 @@ func TestPlanApply_applyPlan(t *testing.T) { // Create the plan with a deployment plan := &structs.Plan{ - Job: alloc.Job, - Deployment: mock.Deployment(), + Job: alloc.Job, + Deployment: dnew, + DeploymentUpdates: updates, } // Apply the plan @@ -123,7 +145,7 @@ func TestPlanApply_applyPlan(t *testing.T) { t.Fatalf("missing alloc") } - // Lookup the deployment + // Lookup the new deployment dout, err := fsmState.DeploymentByID(ws, plan.Deployment.ID) if err != nil { t.Fatalf("err: %v", err) @@ -132,6 +154,18 @@ func TestPlanApply_applyPlan(t *testing.T) { t.Fatalf("missing deployment") } + // Lookup the updated deployment + dout2, err := fsmState.DeploymentByID(ws, oldDeployment.ID) + if err != nil { + t.Fatalf("err: %v", err) + } + if dout2 == nil { + t.Fatalf("missing deployment") + } + if dout2.Status != desiredStatus || dout2.StatusDescription != desiredStatusDescription { + t.Fatalf("bad status: %#v", dout2) + } + // Evict alloc, Register alloc2 allocEvict := new(structs.Allocation) *allocEvict = *alloc @@ -214,6 +248,14 @@ func TestPlanApply_EvalPlan_Simple(t *testing.T) { NodeAllocation: map[string][]*structs.Allocation{ node.ID: []*structs.Allocation{alloc}, }, + Deployment: mock.Deployment(), + DeploymentUpdates: []*structs.DeploymentStatusUpdate{ + { + DeploymentID: structs.GenerateUUID(), + Status: "foo", + StatusDescription: "bar", + }, + }, } pool := NewEvaluatePool(workerPoolSize, workerPoolBufferSize) @@ -229,6 +271,12 @@ func TestPlanApply_EvalPlan_Simple(t *testing.T) { if !reflect.DeepEqual(result.NodeAllocation, plan.NodeAllocation) { t.Fatalf("incorrect node allocations") } + if !reflect.DeepEqual(result.Deployment, plan.Deployment) { + t.Fatalf("incorrect deployment") + } + if !reflect.DeepEqual(result.DeploymentUpdates, plan.DeploymentUpdates) { + t.Fatalf("incorrect deployment updates") + } } func TestPlanApply_EvalPlan_Partial(t *testing.T) { @@ -242,11 +290,17 @@ func TestPlanApply_EvalPlan_Partial(t *testing.T) { alloc := mock.Alloc() alloc2 := mock.Alloc() // Ensure alloc2 does not fit alloc2.Resources = node2.Resources + + // Create a deployment where the allocs are markeda as canaries + d := mock.Deployment() + d.TaskGroups["web"].PlacedCanaries = []string{alloc.ID, alloc2.ID} + plan := &structs.Plan{ NodeAllocation: map[string][]*structs.Allocation{ node.ID: []*structs.Allocation{alloc}, node2.ID: []*structs.Allocation{alloc2}, }, + Deployment: d, } pool := NewEvaluatePool(workerPoolSize, workerPoolBufferSize) @@ -266,6 +320,16 @@ func TestPlanApply_EvalPlan_Partial(t *testing.T) { if _, ok := result.NodeAllocation[node2.ID]; ok { t.Fatalf("should not allow alloc2") } + + // Check the deployment was updated + if result.Deployment == nil || len(result.Deployment.TaskGroups) == 0 { + t.Fatalf("bad: %v", result.Deployment) + } + placedCanaries := result.Deployment.TaskGroups["web"].PlacedCanaries + if len(placedCanaries) != 1 || placedCanaries[0] != alloc.ID { + t.Fatalf("bad: %v", placedCanaries) + } + if result.RefreshIndex != 1001 { t.Fatalf("bad: %d", result.RefreshIndex) } @@ -288,6 +352,14 @@ func TestPlanApply_EvalPlan_Partial_AllAtOnce(t *testing.T) { node.ID: []*structs.Allocation{alloc}, node2.ID: []*structs.Allocation{alloc2}, }, + Deployment: mock.Deployment(), + DeploymentUpdates: []*structs.DeploymentStatusUpdate{ + { + DeploymentID: structs.GenerateUUID(), + Status: "foo", + StatusDescription: "bar", + }, + }, } pool := NewEvaluatePool(workerPoolSize, workerPoolBufferSize) @@ -307,6 +379,9 @@ func TestPlanApply_EvalPlan_Partial_AllAtOnce(t *testing.T) { if result.RefreshIndex != 1001 { t.Fatalf("bad: %d", result.RefreshIndex) } + if result.Deployment != nil || len(result.DeploymentUpdates) != 0 { + t.Fatalf("bad: %v", result) + } } func TestPlanApply_EvalNodePlan_Simple(t *testing.T) {