Skip to content
17 changes: 9 additions & 8 deletions pkg/util/provider/machinecontroller/machine_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,10 @@ func (c *controller) syncNodeTemplates(ctx context.Context, machine *v1alpha1.Ma
taintsChanged := SyncMachineTaints(machine, nodeCopy, lastAppliedALT.Spec.Taints)

var virtualCapacityChanged bool
var desiredVirtualCapacity v1.ResourceList
if machineClass != nil && machineClass.NodeTemplate != nil {
virtualCapacityChanged = SyncVirtualCapacity(machineClass.NodeTemplate.VirtualCapacity, nodeCopy, lastAppliedVirtualCapacity)
desiredVirtualCapacity = machineClass.NodeTemplate.VirtualCapacity
virtualCapacityChanged = SyncVirtualCapacity(desiredVirtualCapacity, nodeCopy, lastAppliedVirtualCapacity)
}

if !initializedNodeAnnotation && !annotationsChanged && !labelsChanged && !taintsChanged && !virtualCapacityChanged {
Expand Down Expand Up @@ -573,8 +575,7 @@ func (c *controller) syncNodeTemplates(ctx context.Context, machine *v1alpha1.Ma

if virtualCapacityChanged {
klog.V(2).Infof("virtualCapacity changed, update Node.Status.Capacity of node %q to %v", getNodeName(machine), node.Status.Capacity)
lastAppliedVirtualCapacity = machineClass.NodeTemplate.VirtualCapacity
currentlyAppliedVirtualCapacityJSONByte, err = json.Marshal(lastAppliedVirtualCapacity)
currentlyAppliedVirtualCapacityJSONByte, err = json.Marshal(desiredVirtualCapacity)
if err != nil {
klog.Errorf("Error occurred while syncing node virtual capacity: %v", err)
return machineutils.ShortRetry, err
Expand Down Expand Up @@ -752,26 +753,26 @@ func SyncMachineTaints(

// SyncVirtualCapacity syncs the MachineClass.NodeTemplate.VirtualCapacity with the Node.Status.Capacity
// It returns true if update is needed else false.
func SyncVirtualCapacity(targetVirtualCapacity v1.ResourceList, node *v1.Node, lastAppliedVirtualCapacity v1.ResourceList) bool {
func SyncVirtualCapacity(desiredVirtualCapacity v1.ResourceList, node *v1.Node, lastAppliedVirtualCapacity v1.ResourceList) bool {
toBeUpdated := false

if node.Status.Capacity == nil {
node.Status.Capacity = v1.ResourceList{}
}
if targetVirtualCapacity == nil {
targetVirtualCapacity = v1.ResourceList{}
if desiredVirtualCapacity == nil {
desiredVirtualCapacity = v1.ResourceList{}
}

// Delete any keys that existed in the past but has been deleted now
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Delete any keys that existed in the past but has been deleted now
// Delete any keys that existed in the past but have been removed now

for prevKey := range lastAppliedVirtualCapacity {
if _, exists := targetVirtualCapacity[prevKey]; !exists {
if _, exists := desiredVirtualCapacity[prevKey]; !exists {
delete(node.Status.Capacity, prevKey)
toBeUpdated = true
}
}

// Add/Update any key that doesn't exist or whose value as changed
for targKey, targQuant := range targetVirtualCapacity {
for targKey, targQuant := range desiredVirtualCapacity {
if nodeQuant, exists := node.Status.Capacity[targKey]; !exists || !nodeQuant.Equal(targQuant) {
node.Status.Capacity[targKey] = targQuant
toBeUpdated = true
Expand Down
245 changes: 244 additions & 1 deletion pkg/util/provider/machinecontroller/machine_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"k8s.io/klog/v2"
"time"

machinev1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
Expand All @@ -22,7 +23,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
)

Expand Down Expand Up @@ -1862,6 +1862,249 @@ var _ = Describe("machine_util", func() {
)
})

Describe("#SyncVirtualCapacity", func() {
type setup struct{}
type action struct {
node *corev1.Node
desiredVirtualCapacity corev1.ResourceList
}
type expect struct {
node *corev1.Node
virtualCapacityChanged bool
}
type data struct {
setup setup
action action
expect expect
}

DescribeTable("##table",
func(data *data) error {
testNode := data.action.node.DeepCopy()
desiredVirtualCapacity := data.action.desiredVirtualCapacity
expectedNode := data.expect.node

var lastAppliedVirtualCapacity corev1.ResourceList
lastAppliedVirtualCapacityJSONString, exists := testNode.Annotations[machineutils.LastAppliedVirtualCapacityAnnotation]
if exists {
err := json.Unmarshal([]byte(lastAppliedVirtualCapacityJSONString), &lastAppliedVirtualCapacity)
if err != nil {
return fmt.Errorf("cannot unmarshall %q annotation: %w", machineutils.LastAppliedVirtualCapacityAnnotation, err)
}
}

virtualCapacityChanged := SyncVirtualCapacity(desiredVirtualCapacity, testNode, lastAppliedVirtualCapacity)

Expect(virtualCapacityChanged).To(Equal(data.expect.virtualCapacityChanged))
Expect(testNode.Status.Capacity).Should(Equal(expectedNode.Status.Capacity))

lastAppliedVirtualCapacityJSONString = expectedNode.Annotations[machineutils.LastAppliedVirtualCapacityAnnotation]
lastAppliedVirtualCapacity = corev1.ResourceList{}
err := json.Unmarshal([]byte(lastAppliedVirtualCapacityJSONString), &lastAppliedVirtualCapacity)
if err != nil {
return fmt.Errorf("cannot unmarshall %q annotation with value %q: %w", machineutils.LastAppliedVirtualCapacityAnnotation, lastAppliedVirtualCapacityJSONString, err)
}
Expect(lastAppliedVirtualCapacity).To(Equal(desiredVirtualCapacity))
return nil
},

Entry("when node.status.capacity has not been changed", &data{
setup: setup{},
action: action{
desiredVirtualCapacity: corev1.ResourceList{
"hc.hana.com/memory": resource.MustParse("1234567"),
},
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/memory\":\"1234567\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("1234567"),
},
},
},
},
expect: expect{
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/memory\":\"1234567\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("1234567"),
},
},
},
virtualCapacityChanged: false,
},
}),

Entry("when virtual resource value is changed in virtualCapacity", &data{
setup: setup{},
action: action{
desiredVirtualCapacity: corev1.ResourceList{
"hc.hana.com/memory": resource.MustParse("2234567"),
},
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/memory\":\"1234567\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("1234567"),
},
},
},
},
expect: expect{
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/memory\":\"2234567\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("2234567"),
},
},
},
virtualCapacityChanged: true,
},
}),

Entry("when virtual resources are added in virtualCapacity", &data{
setup: setup{},
action: action{
desiredVirtualCapacity: corev1.ResourceList{
"hc.hana.com/memory": resource.MustParse("1111111"),
"hc.hana.com/cpu": resource.MustParse("2"),
},
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/memory\":\"1111111\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("1111111"),
},
},
},
},
expect: expect{
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/cpu\":\"2\",\"hc.hana.com/memory\":\"1111111\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/memory": resource.MustParse("1111111"),
"hc.hana.com/cpu": resource.MustParse("2"),
},
},
},
virtualCapacityChanged: true,
},
}),

Entry("when virtual resources are deleted in virtualCapacity", &data{
setup: setup{},
action: action{
desiredVirtualCapacity: corev1.ResourceList{
"hc.hana.com/cpu": resource.MustParse("2"),
},
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/cpu\":\"2\",\"hc.hana.com/memory\":\"1111111\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/cpu": resource.MustParse("2"),
"hc.hana.com/memory": resource.MustParse("1111111"),
},
},
},
},
expect: expect{
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Node",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node-0",
Annotations: map[string]string{
machineutils.LastAppliedVirtualCapacityAnnotation: "{\"hc.hana.com/cpu\":\"2\"}",
},
},
Status: corev1.NodeStatus{
Capacity: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse("1234567"),
"hc.hana.com/cpu": resource.MustParse("2"),
},
},
},
virtualCapacityChanged: true,
},
}),
)
})

Describe("#isMachineStatusSimilar", func() {
type setup struct {
m1, m2 machinev1.MachineStatus
Expand Down