k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/scheduler/framework/plugins/nodeunschedulable/node_unschedulable_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package nodeunschedulable 18 19 import ( 20 "reflect" 21 "testing" 22 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/kubernetes/pkg/scheduler/framework" 25 "k8s.io/kubernetes/test/utils/ktesting" 26 ) 27 28 func TestNodeUnschedulable(t *testing.T) { 29 testCases := []struct { 30 name string 31 pod *v1.Pod 32 node *v1.Node 33 wantStatus *framework.Status 34 }{ 35 { 36 name: "Does not schedule pod to unschedulable node (node.Spec.Unschedulable==true)", 37 pod: &v1.Pod{}, 38 node: &v1.Node{ 39 Spec: v1.NodeSpec{ 40 Unschedulable: true, 41 }, 42 }, 43 wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonUnschedulable), 44 }, 45 { 46 name: "Schedule pod to normal node", 47 pod: &v1.Pod{}, 48 node: &v1.Node{ 49 Spec: v1.NodeSpec{ 50 Unschedulable: false, 51 }, 52 }, 53 }, 54 { 55 name: "Schedule pod with toleration to unschedulable node (node.Spec.Unschedulable==true)", 56 pod: &v1.Pod{ 57 Spec: v1.PodSpec{ 58 Tolerations: []v1.Toleration{ 59 { 60 Key: v1.TaintNodeUnschedulable, 61 Effect: v1.TaintEffectNoSchedule, 62 }, 63 }, 64 }, 65 }, 66 node: &v1.Node{ 67 Spec: v1.NodeSpec{ 68 Unschedulable: true, 69 }, 70 }, 71 }, 72 } 73 74 for _, test := range testCases { 75 nodeInfo := framework.NewNodeInfo() 76 nodeInfo.SetNode(test.node) 77 _, ctx := ktesting.NewTestContext(t) 78 p, err := New(ctx, nil, nil) 79 if err != nil { 80 t.Fatalf("creating plugin: %v", err) 81 } 82 gotStatus := p.(framework.FilterPlugin).Filter(ctx, nil, test.pod, nodeInfo) 83 if !reflect.DeepEqual(gotStatus, test.wantStatus) { 84 t.Errorf("status does not match: %v, want: %v", gotStatus, test.wantStatus) 85 } 86 } 87 } 88 89 func TestIsSchedulableAfterNodeChange(t *testing.T) { 90 testCases := []struct { 91 name string 92 pod *v1.Pod 93 oldObj, newObj interface{} 94 expectedHint framework.QueueingHint 95 expectedErr bool 96 }{ 97 { 98 name: "backoff-wrong-new-object", 99 pod: &v1.Pod{}, 100 newObj: "not-a-node", 101 expectedHint: framework.Queue, 102 expectedErr: true, 103 }, 104 { 105 name: "backoff-wrong-old-object", 106 pod: &v1.Pod{}, 107 newObj: &v1.Node{ 108 Spec: v1.NodeSpec{ 109 Unschedulable: true, 110 }, 111 }, 112 oldObj: "not-a-node", 113 expectedHint: framework.Queue, 114 expectedErr: true, 115 }, 116 { 117 name: "skip-queue-on-unschedulable-node-added", 118 pod: &v1.Pod{}, 119 newObj: &v1.Node{ 120 Spec: v1.NodeSpec{ 121 Unschedulable: true, 122 }, 123 }, 124 expectedHint: framework.QueueSkip, 125 }, 126 { 127 name: "queue-on-schedulable-node-added", 128 pod: &v1.Pod{}, 129 newObj: &v1.Node{ 130 Spec: v1.NodeSpec{ 131 Unschedulable: false, 132 }, 133 }, 134 expectedHint: framework.Queue, 135 }, 136 { 137 name: "skip-unrelated-change", 138 pod: &v1.Pod{}, 139 newObj: &v1.Node{ 140 Spec: v1.NodeSpec{ 141 Unschedulable: true, 142 Taints: []v1.Taint{ 143 { 144 Key: v1.TaintNodeNotReady, 145 Effect: v1.TaintEffectNoExecute, 146 }, 147 }, 148 }, 149 }, 150 oldObj: &v1.Node{ 151 Spec: v1.NodeSpec{ 152 Unschedulable: true, 153 }, 154 }, 155 expectedHint: framework.QueueSkip, 156 }, 157 { 158 name: "queue-on-unschedulable-field-change", 159 pod: &v1.Pod{}, 160 newObj: &v1.Node{ 161 Spec: v1.NodeSpec{ 162 Unschedulable: false, 163 }, 164 }, 165 oldObj: &v1.Node{ 166 Spec: v1.NodeSpec{ 167 Unschedulable: true, 168 }, 169 }, 170 expectedHint: framework.Queue, 171 }, 172 } 173 174 for _, testCase := range testCases { 175 t.Run(testCase.name, func(t *testing.T) { 176 logger, _ := ktesting.NewTestContext(t) 177 pl := &NodeUnschedulable{} 178 got, err := pl.isSchedulableAfterNodeChange(logger, testCase.pod, testCase.oldObj, testCase.newObj) 179 if err != nil && !testCase.expectedErr { 180 t.Errorf("unexpected error: %v", err) 181 } 182 if got != testCase.expectedHint { 183 t.Errorf("isSchedulableAfterNodeChange() = %v, want %v", got, testCase.expectedHint) 184 } 185 }) 186 } 187 }