From 4cbef07d37f74ced75c33e2223ff93e6049a3415 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Fri, 19 Jan 2018 10:09:30 -0600 Subject: [PATCH] Prevent side effect modification of select options when preferred nodes are set --- scheduler/stack.go | 7 ++++--- scheduler/stack_test.go | 11 +++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/scheduler/stack.go b/scheduler/stack.go index 92e65aa04..16a982b7a 100644 --- a/scheduler/stack.go +++ b/scheduler/stack.go @@ -172,13 +172,14 @@ func (s *GenericStack) Select(tg *structs.TaskGroup, options *SelectOptions) (*R if options != nil && len(options.PreferredNodes) > 0 { originalNodes := s.source.nodes s.source.SetNodes(options.PreferredNodes) - options.PreferredNodes = nil - if option, resources := s.Select(tg, options); option != nil { + optionsNew := *options + optionsNew.PreferredNodes = nil + if option, resources := s.Select(tg, &optionsNew); option != nil { s.source.SetNodes(originalNodes) return option, resources } s.source.SetNodes(originalNodes) - return s.Select(tg, options) + return s.Select(tg, &optionsNew) } // Reset the max selector and context diff --git a/scheduler/stack_test.go b/scheduler/stack_test.go index b245ac418..cf8084ea8 100644 --- a/scheduler/stack_test.go +++ b/scheduler/stack_test.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" + "github.com/stretchr/testify/require" ) func BenchmarkServiceStack_With_ComputedClass(b *testing.B) { @@ -140,7 +141,8 @@ func TestServiceStack_Select_PreferringNodes(t *testing.T) { // Create a preferred node preferredNode := mock.Node() - selectOptions := &SelectOptions{PreferredNodes: []*structs.Node{preferredNode}} + prefNodes := []*structs.Node{preferredNode} + selectOptions := &SelectOptions{PreferredNodes: prefNodes} option, _ := stack.Select(job.TaskGroups[0], selectOptions) if option == nil { t.Fatalf("missing node %#v", ctx.Metrics()) @@ -149,12 +151,16 @@ func TestServiceStack_Select_PreferringNodes(t *testing.T) { t.Fatalf("expected: %v, actual: %v", option.Node.ID, preferredNode.ID) } + // Make sure select doesn't have a side effect on preferred nodes + require.Equal(t, prefNodes, selectOptions.PreferredNodes) + // Change the preferred node's kernel to windows and ensure the allocations // are placed elsewhere preferredNode1 := preferredNode.Copy() preferredNode1.Attributes["kernel.name"] = "windows" preferredNode1.ComputeClass() - selectOptions = &SelectOptions{PreferredNodes: []*structs.Node{preferredNode1}} + prefNodes1 := []*structs.Node{preferredNode1} + selectOptions = &SelectOptions{PreferredNodes: prefNodes1} option, _ = stack.Select(job.TaskGroups[0], selectOptions) if option == nil { t.Fatalf("missing node %#v", ctx.Metrics()) @@ -163,6 +169,7 @@ func TestServiceStack_Select_PreferringNodes(t *testing.T) { if option.Node.ID != nodes[0].ID { t.Fatalf("expected: %#v, actual: %#v", nodes[0], option.Node) } + require.Equal(t, prefNodes1, selectOptions.PreferredNodes) } func TestServiceStack_Select_MetricsReset(t *testing.T) {