diff --git a/scheduler/reconcile_util.go b/scheduler/reconcile_util.go index bf60723a1aad..3ca6150bae7b 100644 --- a/scheduler/reconcile_util.go +++ b/scheduler/reconcile_util.go @@ -264,7 +264,7 @@ func newAllocNameIndex(job, taskGroup string, count int, in allocSet) *allocName // bitmapFrom creates a bitmap from the given allocation set and a minimum size // maybe given. The size of the bitmap is as the larger of the passed minimum -// and t the maximum alloc index of the passed input (byte aligned). +// and the maximum alloc index of the passed input (byte aligned). func bitmapFrom(input allocSet, minSize uint) structs.Bitmap { var max uint for _, a := range input { @@ -276,9 +276,16 @@ func bitmapFrom(input allocSet, minSize uint) structs.Bitmap { if l := uint(len(input)); minSize < l { minSize = l } + if max < minSize { max = minSize + } else if max%8 == 0 { + // This may be possible if the job was scaled down. We want to make sure + // that the max index is not byte-alligned otherwise we will overflow + // the bitmap. + max++ } + if max == 0 { max = 8 } diff --git a/scheduler/reconcile_util_test.go b/scheduler/reconcile_util_test.go new file mode 100644 index 000000000000..2229f6098b3c --- /dev/null +++ b/scheduler/reconcile_util_test.go @@ -0,0 +1,31 @@ +package scheduler + +import ( + "testing" + + "github.com/hashicorp/nomad/nomad/structs" +) + +// Test that we properly create the bitmap even when the alloc set includes an +// allocation with a higher count than the current min count and it is byte +// alligned. +// Ensure no regerssion from: https://github.com/hashicorp/nomad/issues/3008 +func TestBitmapFrom(t *testing.T) { + input := map[string]*structs.Allocation{ + "8": { + JobID: "foo", + TaskGroup: "bar", + Name: "foo.bar[8]", + }, + } + b := bitmapFrom(input, 1) + exp := uint(16) + if act := b.Size(); act != exp { + t.Fatalf("got %d; want %d", act, exp) + } + + b = bitmapFrom(input, 8) + if act := b.Size(); act != exp { + t.Fatalf("got %d; want %d", act, exp) + } +}