cleanup: move NodeSchedulingPropertiesChange
This commit is contained in:
		@@ -24,7 +24,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	storagev1 "k8s.io/api/storage/v1"
 | 
						storagev1 "k8s.io/api/storage/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/api/equality"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
						utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
@@ -94,7 +93,7 @@ func (sched *Scheduler) updateNodeInCache(oldObj, newObj interface{}) {
 | 
				
			|||||||
	logger.V(4).Info("Update event for node", "node", klog.KObj(newNode))
 | 
						logger.V(4).Info("Update event for node", "node", klog.KObj(newNode))
 | 
				
			||||||
	nodeInfo := sched.Cache.UpdateNode(logger, oldNode, newNode)
 | 
						nodeInfo := sched.Cache.UpdateNode(logger, oldNode, newNode)
 | 
				
			||||||
	// Only requeue unschedulable pods if the node became more schedulable.
 | 
						// Only requeue unschedulable pods if the node became more schedulable.
 | 
				
			||||||
	for _, evt := range nodeSchedulingPropertiesChange(newNode, oldNode) {
 | 
						for _, evt := range queue.NodeSchedulingPropertiesChange(newNode, oldNode) {
 | 
				
			||||||
		sched.SchedulingQueue.MoveAllToActiveOrBackoffQueue(logger, evt, oldNode, newNode, preCheckForNode(nodeInfo))
 | 
							sched.SchedulingQueue.MoveAllToActiveOrBackoffQueue(logger, evt, oldNode, newNode, preCheckForNode(nodeInfo))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -571,62 +570,6 @@ func addAllEventHandlers(
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func nodeSchedulingPropertiesChange(newNode *v1.Node, oldNode *v1.Node) []framework.ClusterEvent {
 | 
					 | 
				
			||||||
	var events []framework.ClusterEvent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if nodeSpecUnschedulableChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeSpecUnschedulableChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if nodeAllocatableChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeAllocatableChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if nodeLabelsChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeLabelChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if nodeTaintsChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeTaintChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if nodeConditionsChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeConditionChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if nodeAnnotationsChanged(newNode, oldNode) {
 | 
					 | 
				
			||||||
		events = append(events, queue.NodeAnnotationChange)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return events
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeAllocatableChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	return !equality.Semantic.DeepEqual(oldNode.Status.Allocatable, newNode.Status.Allocatable)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeLabelsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	return !equality.Semantic.DeepEqual(oldNode.GetLabels(), newNode.GetLabels())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeTaintsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	return !equality.Semantic.DeepEqual(newNode.Spec.Taints, oldNode.Spec.Taints)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeConditionsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	strip := func(conditions []v1.NodeCondition) map[v1.NodeConditionType]v1.ConditionStatus {
 | 
					 | 
				
			||||||
		conditionStatuses := make(map[v1.NodeConditionType]v1.ConditionStatus, len(conditions))
 | 
					 | 
				
			||||||
		for i := range conditions {
 | 
					 | 
				
			||||||
			conditionStatuses[conditions[i].Type] = conditions[i].Status
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return conditionStatuses
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return !equality.Semantic.DeepEqual(strip(oldNode.Status.Conditions), strip(newNode.Status.Conditions))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeSpecUnschedulableChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	return newNode.Spec.Unschedulable != oldNode.Spec.Unschedulable && !newNode.Spec.Unschedulable
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeAnnotationsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
					 | 
				
			||||||
	return !equality.Semantic.DeepEqual(oldNode.GetAnnotations(), newNode.GetAnnotations())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func preCheckForNode(nodeInfo *framework.NodeInfo) queue.PreEnqueueCheck {
 | 
					func preCheckForNode(nodeInfo *framework.NodeInfo) queue.PreEnqueueCheck {
 | 
				
			||||||
	// Note: the following checks doesn't take preemption into considerations, in very rare
 | 
						// Note: the following checks doesn't take preemption into considerations, in very rare
 | 
				
			||||||
	// cases (e.g., node resizing), "pod" may still fail a check but preemption helps. We deliberately
 | 
						// cases (e.g., node resizing), "pod" may still fail a check but preemption helps. We deliberately
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,6 @@ import (
 | 
				
			|||||||
	resourcev1alpha2 "k8s.io/api/resource/v1alpha2"
 | 
						resourcev1alpha2 "k8s.io/api/resource/v1alpha2"
 | 
				
			||||||
	storagev1 "k8s.io/api/storage/v1"
 | 
						storagev1 "k8s.io/api/storage/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
						"k8s.io/apimachinery/pkg/api/resource"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
					 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
						featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
				
			||||||
	"k8s.io/klog/v2/ktesting"
 | 
						"k8s.io/klog/v2/ktesting"
 | 
				
			||||||
@@ -53,157 +52,6 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/scheduler/util/assumecache"
 | 
						"k8s.io/kubernetes/pkg/scheduler/util/assumecache"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNodeAllocatableChanged(t *testing.T) {
 | 
					 | 
				
			||||||
	newQuantity := func(value int64) resource.Quantity {
 | 
					 | 
				
			||||||
		return *resource.NewQuantity(value, resource.BinarySI)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, test := range []struct {
 | 
					 | 
				
			||||||
		Name           string
 | 
					 | 
				
			||||||
		Changed        bool
 | 
					 | 
				
			||||||
		OldAllocatable v1.ResourceList
 | 
					 | 
				
			||||||
		NewAllocatable v1.ResourceList
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:           "no allocatable resources changed",
 | 
					 | 
				
			||||||
			Changed:        false,
 | 
					 | 
				
			||||||
			OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
					 | 
				
			||||||
			NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:           "new node has more allocatable resources",
 | 
					 | 
				
			||||||
			Changed:        true,
 | 
					 | 
				
			||||||
			OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
					 | 
				
			||||||
			NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024), v1.ResourceStorage: newQuantity(1024)},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	} {
 | 
					 | 
				
			||||||
		t.Run(test.Name, func(t *testing.T) {
 | 
					 | 
				
			||||||
			oldNode := &v1.Node{Status: v1.NodeStatus{Allocatable: test.OldAllocatable}}
 | 
					 | 
				
			||||||
			newNode := &v1.Node{Status: v1.NodeStatus{Allocatable: test.NewAllocatable}}
 | 
					 | 
				
			||||||
			changed := nodeAllocatableChanged(newNode, oldNode)
 | 
					 | 
				
			||||||
			if changed != test.Changed {
 | 
					 | 
				
			||||||
				t.Errorf("nodeAllocatableChanged should be %t, got %t", test.Changed, changed)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestNodeLabelsChanged(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range []struct {
 | 
					 | 
				
			||||||
		Name      string
 | 
					 | 
				
			||||||
		Changed   bool
 | 
					 | 
				
			||||||
		OldLabels map[string]string
 | 
					 | 
				
			||||||
		NewLabels map[string]string
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:      "no labels changed",
 | 
					 | 
				
			||||||
			Changed:   false,
 | 
					 | 
				
			||||||
			OldLabels: map[string]string{"foo": "bar"},
 | 
					 | 
				
			||||||
			NewLabels: map[string]string{"foo": "bar"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		// Labels changed.
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:      "new node has more labels",
 | 
					 | 
				
			||||||
			Changed:   true,
 | 
					 | 
				
			||||||
			OldLabels: map[string]string{"foo": "bar"},
 | 
					 | 
				
			||||||
			NewLabels: map[string]string{"foo": "bar", "test": "value"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	} {
 | 
					 | 
				
			||||||
		t.Run(test.Name, func(t *testing.T) {
 | 
					 | 
				
			||||||
			oldNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: test.OldLabels}}
 | 
					 | 
				
			||||||
			newNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: test.NewLabels}}
 | 
					 | 
				
			||||||
			changed := nodeLabelsChanged(newNode, oldNode)
 | 
					 | 
				
			||||||
			if changed != test.Changed {
 | 
					 | 
				
			||||||
				t.Errorf("Test case %q failed: should be %t, got %t", test.Name, test.Changed, changed)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestNodeTaintsChanged(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range []struct {
 | 
					 | 
				
			||||||
		Name      string
 | 
					 | 
				
			||||||
		Changed   bool
 | 
					 | 
				
			||||||
		OldTaints []v1.Taint
 | 
					 | 
				
			||||||
		NewTaints []v1.Taint
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:      "no taint changed",
 | 
					 | 
				
			||||||
			Changed:   false,
 | 
					 | 
				
			||||||
			OldTaints: []v1.Taint{{Key: "key", Value: "value"}},
 | 
					 | 
				
			||||||
			NewTaints: []v1.Taint{{Key: "key", Value: "value"}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:      "taint value changed",
 | 
					 | 
				
			||||||
			Changed:   true,
 | 
					 | 
				
			||||||
			OldTaints: []v1.Taint{{Key: "key", Value: "value1"}},
 | 
					 | 
				
			||||||
			NewTaints: []v1.Taint{{Key: "key", Value: "value2"}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	} {
 | 
					 | 
				
			||||||
		t.Run(test.Name, func(t *testing.T) {
 | 
					 | 
				
			||||||
			oldNode := &v1.Node{Spec: v1.NodeSpec{Taints: test.OldTaints}}
 | 
					 | 
				
			||||||
			newNode := &v1.Node{Spec: v1.NodeSpec{Taints: test.NewTaints}}
 | 
					 | 
				
			||||||
			changed := nodeTaintsChanged(newNode, oldNode)
 | 
					 | 
				
			||||||
			if changed != test.Changed {
 | 
					 | 
				
			||||||
				t.Errorf("Test case %q failed: should be %t, not %t", test.Name, test.Changed, changed)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestNodeConditionsChanged(t *testing.T) {
 | 
					 | 
				
			||||||
	nodeConditionType := reflect.TypeOf(v1.NodeCondition{})
 | 
					 | 
				
			||||||
	if nodeConditionType.NumField() != 6 {
 | 
					 | 
				
			||||||
		t.Errorf("NodeCondition type has changed. The nodeConditionsChanged() function must be reevaluated.")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, test := range []struct {
 | 
					 | 
				
			||||||
		Name          string
 | 
					 | 
				
			||||||
		Changed       bool
 | 
					 | 
				
			||||||
		OldConditions []v1.NodeCondition
 | 
					 | 
				
			||||||
		NewConditions []v1.NodeCondition
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:          "no condition changed",
 | 
					 | 
				
			||||||
			Changed:       false,
 | 
					 | 
				
			||||||
			OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
					 | 
				
			||||||
			NewConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:          "only LastHeartbeatTime changed",
 | 
					 | 
				
			||||||
			Changed:       false,
 | 
					 | 
				
			||||||
			OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(1, 0)}},
 | 
					 | 
				
			||||||
			NewConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(2, 0)}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:          "new node has more healthy conditions",
 | 
					 | 
				
			||||||
			Changed:       true,
 | 
					 | 
				
			||||||
			OldConditions: []v1.NodeCondition{},
 | 
					 | 
				
			||||||
			NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:          "new node has less unhealthy conditions",
 | 
					 | 
				
			||||||
			Changed:       true,
 | 
					 | 
				
			||||||
			OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
					 | 
				
			||||||
			NewConditions: []v1.NodeCondition{},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Name:          "condition status changed",
 | 
					 | 
				
			||||||
			Changed:       true,
 | 
					 | 
				
			||||||
			OldConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}},
 | 
					 | 
				
			||||||
			NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	} {
 | 
					 | 
				
			||||||
		t.Run(test.Name, func(t *testing.T) {
 | 
					 | 
				
			||||||
			oldNode := &v1.Node{Status: v1.NodeStatus{Conditions: test.OldConditions}}
 | 
					 | 
				
			||||||
			newNode := &v1.Node{Status: v1.NodeStatus{Conditions: test.NewConditions}}
 | 
					 | 
				
			||||||
			changed := nodeConditionsChanged(newNode, oldNode)
 | 
					 | 
				
			||||||
			if changed != test.Changed {
 | 
					 | 
				
			||||||
				t.Errorf("Test case %q failed: should be %t, got %t", test.Name, test.Changed, changed)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestUpdatePodInCache(t *testing.T) {
 | 
					func TestUpdatePodInCache(t *testing.T) {
 | 
				
			||||||
	ttl := 10 * time.Second
 | 
						ttl := 10 * time.Second
 | 
				
			||||||
	nodeName := "node"
 | 
						nodeName := "node"
 | 
				
			||||||
@@ -574,91 +422,3 @@ func TestAdmissionCheck(t *testing.T) {
 | 
				
			|||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestNodeSchedulingPropertiesChange(t *testing.T) {
 | 
					 | 
				
			||||||
	testCases := []struct {
 | 
					 | 
				
			||||||
		name       string
 | 
					 | 
				
			||||||
		newNode    *v1.Node
 | 
					 | 
				
			||||||
		oldNode    *v1.Node
 | 
					 | 
				
			||||||
		wantEvents []framework.ClusterEvent
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:       "no specific changed applied",
 | 
					 | 
				
			||||||
			newNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
					 | 
				
			||||||
			oldNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: nil,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:       "only node spec unavailable changed",
 | 
					 | 
				
			||||||
			newNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
					 | 
				
			||||||
			oldNode:    st.MakeNode().Unschedulable(true).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeSpecUnschedulableChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "only node allocatable changed",
 | 
					 | 
				
			||||||
			newNode: st.MakeNode().Capacity(map[v1.ResourceName]string{
 | 
					 | 
				
			||||||
				v1.ResourceCPU:                     "1000m",
 | 
					 | 
				
			||||||
				v1.ResourceMemory:                  "100m",
 | 
					 | 
				
			||||||
				v1.ResourceName("example.com/foo"): "1"},
 | 
					 | 
				
			||||||
			).Obj(),
 | 
					 | 
				
			||||||
			oldNode: st.MakeNode().Capacity(map[v1.ResourceName]string{
 | 
					 | 
				
			||||||
				v1.ResourceCPU:                     "1000m",
 | 
					 | 
				
			||||||
				v1.ResourceMemory:                  "100m",
 | 
					 | 
				
			||||||
				v1.ResourceName("example.com/foo"): "2"},
 | 
					 | 
				
			||||||
			).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeAllocatableChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:       "only node label changed",
 | 
					 | 
				
			||||||
			newNode:    st.MakeNode().Label("foo", "bar").Obj(),
 | 
					 | 
				
			||||||
			oldNode:    st.MakeNode().Label("foo", "fuz").Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeLabelChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "only node taint changed",
 | 
					 | 
				
			||||||
			newNode: st.MakeNode().Taints([]v1.Taint{
 | 
					 | 
				
			||||||
				{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectNoSchedule},
 | 
					 | 
				
			||||||
			}).Obj(),
 | 
					 | 
				
			||||||
			oldNode: st.MakeNode().Taints([]v1.Taint{
 | 
					 | 
				
			||||||
				{Key: v1.TaintNodeUnschedulable, Value: "foo", Effect: v1.TaintEffectNoSchedule},
 | 
					 | 
				
			||||||
			}).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeTaintChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:       "only node annotation changed",
 | 
					 | 
				
			||||||
			newNode:    st.MakeNode().Annotation("foo", "bar").Obj(),
 | 
					 | 
				
			||||||
			oldNode:    st.MakeNode().Annotation("foo", "fuz").Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeAnnotationChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:    "only node condition changed",
 | 
					 | 
				
			||||||
			newNode: st.MakeNode().Obj(),
 | 
					 | 
				
			||||||
			oldNode: st.MakeNode().Condition(
 | 
					 | 
				
			||||||
				v1.NodeReady,
 | 
					 | 
				
			||||||
				v1.ConditionTrue,
 | 
					 | 
				
			||||||
				"Ready",
 | 
					 | 
				
			||||||
				"Ready",
 | 
					 | 
				
			||||||
			).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeConditionChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "both node label and node taint changed",
 | 
					 | 
				
			||||||
			newNode: st.MakeNode().
 | 
					 | 
				
			||||||
				Label("foo", "bar").
 | 
					 | 
				
			||||||
				Taints([]v1.Taint{
 | 
					 | 
				
			||||||
					{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectNoSchedule},
 | 
					 | 
				
			||||||
				}).Obj(),
 | 
					 | 
				
			||||||
			oldNode: st.MakeNode().Taints([]v1.Taint{
 | 
					 | 
				
			||||||
				{Key: v1.TaintNodeUnschedulable, Value: "foo", Effect: v1.TaintEffectNoSchedule},
 | 
					 | 
				
			||||||
			}).Obj(),
 | 
					 | 
				
			||||||
			wantEvents: []framework.ClusterEvent{queue.NodeLabelChange, queue.NodeTaintChange},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, tc := range testCases {
 | 
					 | 
				
			||||||
		gotEvents := nodeSchedulingPropertiesChange(tc.newNode, tc.oldNode)
 | 
					 | 
				
			||||||
		if diff := cmp.Diff(tc.wantEvents, gotEvents); diff != "" {
 | 
					 | 
				
			||||||
			t.Errorf("unexpected event (-want, +got):\n%s", diff)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@ limitations under the License.
 | 
				
			|||||||
package queue
 | 
					package queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/api/equality"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/scheduler/framework"
 | 
						"k8s.io/kubernetes/pkg/scheduler/framework"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,3 +91,59 @@ var (
 | 
				
			|||||||
	// UnschedulableTimeout is the event when a pod stays in unschedulable for longer than timeout.
 | 
						// UnschedulableTimeout is the event when a pod stays in unschedulable for longer than timeout.
 | 
				
			||||||
	UnschedulableTimeout = framework.ClusterEvent{Resource: framework.WildCard, ActionType: framework.All, Label: "UnschedulableTimeout"}
 | 
						UnschedulableTimeout = framework.ClusterEvent{Resource: framework.WildCard, ActionType: framework.All, Label: "UnschedulableTimeout"}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NodeSchedulingPropertiesChange(newNode *v1.Node, oldNode *v1.Node) []framework.ClusterEvent {
 | 
				
			||||||
 | 
						var events []framework.ClusterEvent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if nodeSpecUnschedulableChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeSpecUnschedulableChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeAllocatableChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeAllocatableChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeLabelsChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeLabelChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeTaintsChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeTaintChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeConditionsChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeConditionChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeAnnotationsChanged(newNode, oldNode) {
 | 
				
			||||||
 | 
							events = append(events, NodeAnnotationChange)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return events
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeAllocatableChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						return !equality.Semantic.DeepEqual(oldNode.Status.Allocatable, newNode.Status.Allocatable)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeLabelsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						return !equality.Semantic.DeepEqual(oldNode.GetLabels(), newNode.GetLabels())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeTaintsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						return !equality.Semantic.DeepEqual(newNode.Spec.Taints, oldNode.Spec.Taints)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeConditionsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						strip := func(conditions []v1.NodeCondition) map[v1.NodeConditionType]v1.ConditionStatus {
 | 
				
			||||||
 | 
							conditionStatuses := make(map[v1.NodeConditionType]v1.ConditionStatus, len(conditions))
 | 
				
			||||||
 | 
							for i := range conditions {
 | 
				
			||||||
 | 
								conditionStatuses[conditions[i].Type] = conditions[i].Status
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return conditionStatuses
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return !equality.Semantic.DeepEqual(strip(oldNode.Status.Conditions), strip(newNode.Status.Conditions))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeSpecUnschedulableChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						return newNode.Spec.Unschedulable != oldNode.Spec.Unschedulable && !newNode.Spec.Unschedulable
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func nodeAnnotationsChanged(newNode *v1.Node, oldNode *v1.Node) bool {
 | 
				
			||||||
 | 
						return !equality.Semantic.DeepEqual(oldNode.GetAnnotations(), newNode.GetAnnotations())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										265
									
								
								pkg/scheduler/internal/queue/events_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								pkg/scheduler/internal/queue/events_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,265 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2024 The Kubernetes Authors.
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/go-cmp/cmp"
 | 
				
			||||||
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/api/resource"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/scheduler/framework"
 | 
				
			||||||
 | 
						st "k8s.io/kubernetes/pkg/scheduler/testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeAllocatableChanged(t *testing.T) {
 | 
				
			||||||
 | 
						newQuantity := func(value int64) resource.Quantity {
 | 
				
			||||||
 | 
							return *resource.NewQuantity(value, resource.BinarySI)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range []struct {
 | 
				
			||||||
 | 
							Name           string
 | 
				
			||||||
 | 
							Changed        bool
 | 
				
			||||||
 | 
							OldAllocatable v1.ResourceList
 | 
				
			||||||
 | 
							NewAllocatable v1.ResourceList
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:           "no allocatable resources changed",
 | 
				
			||||||
 | 
								Changed:        false,
 | 
				
			||||||
 | 
								OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
				
			||||||
 | 
								NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:           "new node has more allocatable resources",
 | 
				
			||||||
 | 
								Changed:        true,
 | 
				
			||||||
 | 
								OldAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024)},
 | 
				
			||||||
 | 
								NewAllocatable: v1.ResourceList{v1.ResourceMemory: newQuantity(1024), v1.ResourceStorage: newQuantity(1024)},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							t.Run(test.Name, func(t *testing.T) {
 | 
				
			||||||
 | 
								oldNode := &v1.Node{Status: v1.NodeStatus{Allocatable: test.OldAllocatable}}
 | 
				
			||||||
 | 
								newNode := &v1.Node{Status: v1.NodeStatus{Allocatable: test.NewAllocatable}}
 | 
				
			||||||
 | 
								changed := nodeAllocatableChanged(newNode, oldNode)
 | 
				
			||||||
 | 
								if changed != test.Changed {
 | 
				
			||||||
 | 
									t.Errorf("nodeAllocatableChanged should be %t, got %t", test.Changed, changed)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeLabelsChanged(t *testing.T) {
 | 
				
			||||||
 | 
						for _, test := range []struct {
 | 
				
			||||||
 | 
							Name      string
 | 
				
			||||||
 | 
							Changed   bool
 | 
				
			||||||
 | 
							OldLabels map[string]string
 | 
				
			||||||
 | 
							NewLabels map[string]string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:      "no labels changed",
 | 
				
			||||||
 | 
								Changed:   false,
 | 
				
			||||||
 | 
								OldLabels: map[string]string{"foo": "bar"},
 | 
				
			||||||
 | 
								NewLabels: map[string]string{"foo": "bar"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Labels changed.
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:      "new node has more labels",
 | 
				
			||||||
 | 
								Changed:   true,
 | 
				
			||||||
 | 
								OldLabels: map[string]string{"foo": "bar"},
 | 
				
			||||||
 | 
								NewLabels: map[string]string{"foo": "bar", "test": "value"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							t.Run(test.Name, func(t *testing.T) {
 | 
				
			||||||
 | 
								oldNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: test.OldLabels}}
 | 
				
			||||||
 | 
								newNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: test.NewLabels}}
 | 
				
			||||||
 | 
								changed := nodeLabelsChanged(newNode, oldNode)
 | 
				
			||||||
 | 
								if changed != test.Changed {
 | 
				
			||||||
 | 
									t.Errorf("Test case %q failed: should be %t, got %t", test.Name, test.Changed, changed)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeTaintsChanged(t *testing.T) {
 | 
				
			||||||
 | 
						for _, test := range []struct {
 | 
				
			||||||
 | 
							Name      string
 | 
				
			||||||
 | 
							Changed   bool
 | 
				
			||||||
 | 
							OldTaints []v1.Taint
 | 
				
			||||||
 | 
							NewTaints []v1.Taint
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:      "no taint changed",
 | 
				
			||||||
 | 
								Changed:   false,
 | 
				
			||||||
 | 
								OldTaints: []v1.Taint{{Key: "key", Value: "value"}},
 | 
				
			||||||
 | 
								NewTaints: []v1.Taint{{Key: "key", Value: "value"}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:      "taint value changed",
 | 
				
			||||||
 | 
								Changed:   true,
 | 
				
			||||||
 | 
								OldTaints: []v1.Taint{{Key: "key", Value: "value1"}},
 | 
				
			||||||
 | 
								NewTaints: []v1.Taint{{Key: "key", Value: "value2"}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							t.Run(test.Name, func(t *testing.T) {
 | 
				
			||||||
 | 
								oldNode := &v1.Node{Spec: v1.NodeSpec{Taints: test.OldTaints}}
 | 
				
			||||||
 | 
								newNode := &v1.Node{Spec: v1.NodeSpec{Taints: test.NewTaints}}
 | 
				
			||||||
 | 
								changed := nodeTaintsChanged(newNode, oldNode)
 | 
				
			||||||
 | 
								if changed != test.Changed {
 | 
				
			||||||
 | 
									t.Errorf("Test case %q failed: should be %t, not %t", test.Name, test.Changed, changed)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeConditionsChanged(t *testing.T) {
 | 
				
			||||||
 | 
						nodeConditionType := reflect.TypeOf(v1.NodeCondition{})
 | 
				
			||||||
 | 
						if nodeConditionType.NumField() != 6 {
 | 
				
			||||||
 | 
							t.Errorf("NodeCondition type has changed. The nodeConditionsChanged() function must be reevaluated.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range []struct {
 | 
				
			||||||
 | 
							Name          string
 | 
				
			||||||
 | 
							Changed       bool
 | 
				
			||||||
 | 
							OldConditions []v1.NodeCondition
 | 
				
			||||||
 | 
							NewConditions []v1.NodeCondition
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:          "no condition changed",
 | 
				
			||||||
 | 
								Changed:       false,
 | 
				
			||||||
 | 
								OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
				
			||||||
 | 
								NewConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:          "only LastHeartbeatTime changed",
 | 
				
			||||||
 | 
								Changed:       false,
 | 
				
			||||||
 | 
								OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(1, 0)}},
 | 
				
			||||||
 | 
								NewConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(2, 0)}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:          "new node has more healthy conditions",
 | 
				
			||||||
 | 
								Changed:       true,
 | 
				
			||||||
 | 
								OldConditions: []v1.NodeCondition{},
 | 
				
			||||||
 | 
								NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:          "new node has less unhealthy conditions",
 | 
				
			||||||
 | 
								Changed:       true,
 | 
				
			||||||
 | 
								OldConditions: []v1.NodeCondition{{Type: v1.NodeDiskPressure, Status: v1.ConditionTrue}},
 | 
				
			||||||
 | 
								NewConditions: []v1.NodeCondition{},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:          "condition status changed",
 | 
				
			||||||
 | 
								Changed:       true,
 | 
				
			||||||
 | 
								OldConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionFalse}},
 | 
				
			||||||
 | 
								NewConditions: []v1.NodeCondition{{Type: v1.NodeReady, Status: v1.ConditionTrue}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							t.Run(test.Name, func(t *testing.T) {
 | 
				
			||||||
 | 
								oldNode := &v1.Node{Status: v1.NodeStatus{Conditions: test.OldConditions}}
 | 
				
			||||||
 | 
								newNode := &v1.Node{Status: v1.NodeStatus{Conditions: test.NewConditions}}
 | 
				
			||||||
 | 
								changed := nodeConditionsChanged(newNode, oldNode)
 | 
				
			||||||
 | 
								if changed != test.Changed {
 | 
				
			||||||
 | 
									t.Errorf("Test case %q failed: should be %t, got %t", test.Name, test.Changed, changed)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNodeSchedulingPropertiesChange(t *testing.T) {
 | 
				
			||||||
 | 
						testCases := []struct {
 | 
				
			||||||
 | 
							name       string
 | 
				
			||||||
 | 
							newNode    *v1.Node
 | 
				
			||||||
 | 
							oldNode    *v1.Node
 | 
				
			||||||
 | 
							wantEvents []framework.ClusterEvent
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "no specific changed applied",
 | 
				
			||||||
 | 
								newNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
				
			||||||
 | 
								oldNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
				
			||||||
 | 
								wantEvents: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "only node spec unavailable changed",
 | 
				
			||||||
 | 
								newNode:    st.MakeNode().Unschedulable(false).Obj(),
 | 
				
			||||||
 | 
								oldNode:    st.MakeNode().Unschedulable(true).Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeSpecUnschedulableChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "only node allocatable changed",
 | 
				
			||||||
 | 
								newNode: st.MakeNode().Capacity(map[v1.ResourceName]string{
 | 
				
			||||||
 | 
									v1.ResourceCPU:                     "1000m",
 | 
				
			||||||
 | 
									v1.ResourceMemory:                  "100m",
 | 
				
			||||||
 | 
									v1.ResourceName("example.com/foo"): "1"},
 | 
				
			||||||
 | 
								).Obj(),
 | 
				
			||||||
 | 
								oldNode: st.MakeNode().Capacity(map[v1.ResourceName]string{
 | 
				
			||||||
 | 
									v1.ResourceCPU:                     "1000m",
 | 
				
			||||||
 | 
									v1.ResourceMemory:                  "100m",
 | 
				
			||||||
 | 
									v1.ResourceName("example.com/foo"): "2"},
 | 
				
			||||||
 | 
								).Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeAllocatableChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "only node label changed",
 | 
				
			||||||
 | 
								newNode:    st.MakeNode().Label("foo", "bar").Obj(),
 | 
				
			||||||
 | 
								oldNode:    st.MakeNode().Label("foo", "fuz").Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeLabelChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "only node taint changed",
 | 
				
			||||||
 | 
								newNode: st.MakeNode().Taints([]v1.Taint{
 | 
				
			||||||
 | 
									{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectNoSchedule},
 | 
				
			||||||
 | 
								}).Obj(),
 | 
				
			||||||
 | 
								oldNode: st.MakeNode().Taints([]v1.Taint{
 | 
				
			||||||
 | 
									{Key: v1.TaintNodeUnschedulable, Value: "foo", Effect: v1.TaintEffectNoSchedule},
 | 
				
			||||||
 | 
								}).Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeTaintChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:       "only node annotation changed",
 | 
				
			||||||
 | 
								newNode:    st.MakeNode().Annotation("foo", "bar").Obj(),
 | 
				
			||||||
 | 
								oldNode:    st.MakeNode().Annotation("foo", "fuz").Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeAnnotationChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "only node condition changed",
 | 
				
			||||||
 | 
								newNode: st.MakeNode().Obj(),
 | 
				
			||||||
 | 
								oldNode: st.MakeNode().Condition(
 | 
				
			||||||
 | 
									v1.NodeReady,
 | 
				
			||||||
 | 
									v1.ConditionTrue,
 | 
				
			||||||
 | 
									"Ready",
 | 
				
			||||||
 | 
									"Ready",
 | 
				
			||||||
 | 
								).Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeConditionChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "both node label and node taint changed",
 | 
				
			||||||
 | 
								newNode: st.MakeNode().
 | 
				
			||||||
 | 
									Label("foo", "bar").
 | 
				
			||||||
 | 
									Taints([]v1.Taint{
 | 
				
			||||||
 | 
										{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectNoSchedule},
 | 
				
			||||||
 | 
									}).Obj(),
 | 
				
			||||||
 | 
								oldNode: st.MakeNode().Taints([]v1.Taint{
 | 
				
			||||||
 | 
									{Key: v1.TaintNodeUnschedulable, Value: "foo", Effect: v1.TaintEffectNoSchedule},
 | 
				
			||||||
 | 
								}).Obj(),
 | 
				
			||||||
 | 
								wantEvents: []framework.ClusterEvent{NodeLabelChange, NodeTaintChange},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, tc := range testCases {
 | 
				
			||||||
 | 
							gotEvents := NodeSchedulingPropertiesChange(tc.newNode, tc.oldNode)
 | 
				
			||||||
 | 
							if diff := cmp.Diff(tc.wantEvents, gotEvents); diff != "" {
 | 
				
			||||||
 | 
								t.Errorf("unexpected event (-want, +got):\n%s", diff)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user