Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
BUG FIXES:
* config: Fixed a bug where the Nomad strategy and target plugins would fail to connect to Nomad's Task API socket [[GH-966](https://github.com/hashicorp/nomad-autoscaler/pull/966)]

IMPROVEMENTS:
* scaleutils: Add new node selector option `oldest_create_index` to select nodes with the oldest creation date [[GH-961](https://github.com/hashicorp/nomad-autoscaler/pull/961)]

## 0.4.5 (August 13, 2024)

IMPROVEMENTS:
* build: Updated to Go 1.22.6 and alpine to 3.20 [[GH-943](https://github.com/hashicorp/nomad-autoscaler/pull/943)]
* build: Updated Nomad API dependency to 1.8.3 [[GH-950](https://github.com/hashicorp/nomad-autoscaler/pull/950)]
* build: Updated to Go 1.22.6 and alpine to 3.20 [[GH-943](https://github.com/hashicorp/nomad-autoscaler/pull/943)]
* build: Updated Nomad API dependency to 1.8.3 [[GH-950](https://github.com/hashicorp/nomad-autoscaler/pull/950)]

BUG FIXES:
* security: Fix incorrect conversion between integer types [[GH-946](https://github.com/hashicorp/nomad-autoscaler/pull/946)]
* security: Fix incorrect conversion between integer types [[GH-946](https://github.com/hashicorp/nomad-autoscaler/pull/946)]

## 0.4.4 (June 4, 2024)

IMPROVEMENTS:
* agent: Update Nomad API dependency to v1.8.0 [[GH-909](https://github.com/hashicorp/nomad-autoscaler/pull/909)]
* plugin/strategy/pass-through: Add new configuration `max_scale_up` and `max_scale_down` to allow restricting how much change is applied on each scaling event [[GH-881](https://github.com/hashicorp/nomad-autoscaler/pull/881)]
* agent: Update Nomad API dependency to v1.8.0 [[GH-909](https://github.com/hashicorp/nomad-autoscaler/pull/909)]
* plugin/strategy/pass-through: Add new configuration `max_scale_up` and `max_scale_down` to allow restricting how much change is applied on each scaling event [[GH-881](https://github.com/hashicorp/nomad-autoscaler/pull/881)]

## 0.4.3 (March 12, 2024)

Expand Down
43 changes: 43 additions & 0 deletions sdk/helper/scaleutils/nodeselector/oldest_create_index.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package nodeselector

import (
"github.com/hashicorp/nomad-autoscaler/sdk"
"github.com/hashicorp/nomad/api"
)

// oldestCreateIndexClusterScaleInNodeSelector is the NodeSelector
// implementation of the ClusterScaleInNodeSelector interface. It selects nodes
// based off the list ordering from Nomad and is the default selector.
type oldestCreateIndexClusterScaleInNodeSelector struct{}

// newoldestCreateIndexClusterScaleInNodeSelector returns a new
// oldestCreateIndexClusterScaleInNodeSelector implementation of the
// ClusterScaleInNodeSelector interface.
func newOldestCreateIndexClusterScaleInNodeSelector() ClusterScaleInNodeSelector {
return &oldestCreateIndexClusterScaleInNodeSelector{}
}

// Name satisfies the Name function on the ClusterScaleInNodeSelector
// interface.
func (n *oldestCreateIndexClusterScaleInNodeSelector) Name() string {
return sdk.TargetNodeSelectorStrategyOldestCreateIndex
}

// Select satisfies the Select function on the ClusterScaleInNodeSelector
// interface.
func (n *oldestCreateIndexClusterScaleInNodeSelector) Select(nodes []*api.NodeListStub, num int) []*api.NodeListStub {

last_index := len(nodes) - 1
if len(nodes) < num {
num = len(nodes)
}
out := make([]*api.NodeListStub, num)

for i := num - 1; i >= 0; i-- {
out[i] = nodes[(last_index)-i]
}
return out
}
56 changes: 56 additions & 0 deletions sdk/helper/scaleutils/nodeselector/oldest_create_index_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package nodeselector

import (
"testing"

"github.com/hashicorp/nomad/api"
"github.com/shoenig/test/must"
)

func Test_oldestClusterScaleInNodeSelectorName(t *testing.T) {
must.Eq(t, "oldest_create_index", newOldestCreateIndexClusterScaleInNodeSelector().Name())
}

func Test_oldestClusterScaleInNodeSelector_Select(t *testing.T) {
testCases := []struct {
inputNodes []*api.NodeListStub
inputNum int
expectedOutput []*api.NodeListStub
name string
}{
{
inputNodes: []*api.NodeListStub{
{ID: "8d01d8fe-3c6b-0fdd-ebbc-a8b5cbb9c00c"},
{ID: "a6604683-fd65-c913-77ee-a0a15b8e88e9"},
},
inputNum: 1,
expectedOutput: []*api.NodeListStub{
{ID: "a6604683-fd65-c913-77ee-a0a15b8e88e9"},
},
name: "single selection needed",
},

{
inputNodes: []*api.NodeListStub{
{ID: "8d01d8fe-3c6b-0fdd-ebbc-a8b5cbb9c00c"},
{ID: "a6604683-fd65-c913-77ee-a0a15b8e88e9"},
},
inputNum: 3,
expectedOutput: []*api.NodeListStub{
{ID: "a6604683-fd65-c913-77ee-a0a15b8e88e9"},
{ID: "8d01d8fe-3c6b-0fdd-ebbc-a8b5cbb9c00c"},
},
name: "multiple selection",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actualOutput := newOldestCreateIndexClusterScaleInNodeSelector().Select(tc.inputNodes, tc.inputNum)
must.Eq(t, tc.expectedOutput, actualOutput)
})
}
}
2 changes: 2 additions & 0 deletions sdk/helper/scaleutils/nodeselector/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ func NewSelector(cfg map[string]string, client *api.Client, log hclog.Logger) (C
return newEmptyClusterScaleInNodeSelector(client, log, false), nil
case sdk.TargetNodeSelectorStrategyEmptyIgnoreSystemJobs:
return newEmptyClusterScaleInNodeSelector(client, log, true), nil
case sdk.TargetNodeSelectorStrategyOldestCreateIndex:
return newOldestCreateIndexClusterScaleInNodeSelector(), nil
default:
return nil, fmt.Errorf("unsupported node selector strategy: %v", val)
}
Expand Down
4 changes: 4 additions & 0 deletions sdk/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ const (
// node selection strategy that only picks nodes without non-terminal
// allocations, without considering system jobs.
TargetNodeSelectorStrategyEmptyIgnoreSystemJobs = "empty_ignore_system"

// TargetNodeSelectorStrategyEmptyIgnoreSystemJobs is the cluster scale-in
// node selection strategy that picks the oldest running nodes
TargetNodeSelectorStrategyOldestCreateIndex = "oldest_create_index"
)

// TargetConfigConflictingClusterParams is a list containing horizontal cluster
Expand Down