diff --git a/scheduler/spread.go b/scheduler/spread.go index 669a7507904..41846382dfa 100644 --- a/scheduler/spread.go +++ b/scheduler/spread.go @@ -214,7 +214,12 @@ func evenSpreadScoreBoost(pset *propertySet, option *structs.Node) float64 { } else if minCount == maxCount { // Maximum possible penalty when the distribution is even return -1.0 + } else if minCount == 0 { + // Current attribute count is equal to min and both are zero. This means no allocations + // were placed for this attribute value yet. Should get the maximum possible boost. + return 1.0 } + // Penalty based on delta from max value delta := int(maxCount - minCount) deltaBoost = float64(delta) / float64(minCount) diff --git a/scheduler/spread_test.go b/scheduler/spread_test.go index 83fb2749f94..9b6d6309dc6 100644 --- a/scheduler/spread_test.go +++ b/scheduler/spread_test.go @@ -1,6 +1,7 @@ package scheduler import ( + "math" "testing" "fmt" @@ -311,6 +312,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) { } for _, rn := range out { require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore)) + } // Update the plan to add allocs to nodes in dc1 @@ -543,3 +545,26 @@ func TestSpreadIterator_MaxPenalty(t *testing.T) { } } + +func Test_evenSpreadScoreBoost(t *testing.T) { + pset := &propertySet{ + existingValues: map[string]uint64{}, + proposedValues: map[string]uint64{ + "dc2": 1, + "dc1": 1, + "dc3": 1, + }, + clearedValues: map[string]uint64{ + "dc2": 1, + "dc3": 1, + }, + targetAttribute: "${node.datacenter}", + } + + opt := &structs.Node{ + Datacenter: "dc2", + } + boost := evenSpreadScoreBoost(pset, opt) + require.False(t, math.IsInf(boost, 1)) + require.Equal(t, 1.0, boost) +}