Code change:
t.Errorf("Expected binder %q but got %q", expectedBinderType, binderType) } } <ins> func TestNodeAllocatableChanged(t *testing.T) { newQuantity := func(value int64) resource.Quantity { return *resource.NewQuantity(value, resource.BinarySI) } for _, c := 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)}, }, } { oldNode := &v1.Node{Status: v1.NodeStatus{Allocatable: c.OldAllocatable}} newNode := &v1.Node{Status: v1.NodeStatus{Allocatable: c.NewAllocatable}} changed := nodeAllocatableChanged(newNode, oldNode) if changed != c.Changed { t.Errorf("nodeAllocatableChanged should be %t, got %t", c.Changed, changed) } } } func TestNodeLabelsChanged(t *testing.T) { for _, c := 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"}, }, } { oldNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: c.OldLabels}} newNode := &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: c.NewLabels}} changed := nodeLabelsChanged(newNode, oldNode) if changed != c.Changed { t.Errorf("Test case %q failed: should be %t, got %t", c.Name, c.Changed, changed) } } } func TestNodeTaintsChanged(t *testing.T) { for _, c := 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"}}, }, } { oldNode := &v1.Node{Spec: v1.NodeSpec{Taints: c.OldTaints}} newNode := &v1.Node{Spec: v1.NodeSpec{Taints: c.NewTaints}} changed := nodeTaintsChanged(newNode, oldNode) if changed != c.Changed { t.Errorf("Test case %q failed: should be %t, not %t", c.Name, c.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 _, c := range []struct { Name          string Changed       bool OldConditions []v1.NodeCondition NewConditions []v1.NodeCondition }{ { Name:          "no condition changed", Changed:       false, OldConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}, NewConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue}}, }, { Name:          "only LastHeartbeatTime changed", Changed:       false, OldConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, Status: v1.ConditionTrue, LastHeartbeatTime: metav1.Unix(1, 0)}}, NewConditions: []v1.NodeCondition{{Type: v1.NodeOutOfDisk, 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.NodeOutOfDisk, 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}}, }, } { oldNode := &v1.Node{Status: v1.NodeStatus{Conditions: c.OldConditions}} newNode := &v1.Node{Status: v1.NodeStatus{Conditions: c.NewConditions}} changed := nodeConditionsChanged(newNode, oldNode) if changed != c.Changed { t.Errorf("Test case %q failed: should be %t, got %t", c.Name, c.Changed, changed) } } } </ins>

Related discussion:
text: If it can be changed, I will add this filter later, otherwise I think we can keep the current implementation to make the compare operation simpler and faster. What's more, just as I said in the PR's description, I'm not sure how much side effects this change has on scheduler's resource consumption, as it always copy node's conditions before comparison.
I am thinking whether we could move this logic(whether node became more schedulable) to kubelet, kubelet reports it through heartbeats.