diff --git a/pkg/controller/daemon/daemon_controller.go b/pkg/controller/daemon/daemon_controller.go index 82d4e0f32f9..1fedc7b1c5f 100644 --- a/pkg/controller/daemon/daemon_controller.go +++ b/pkg/controller/daemon/daemon_controller.go @@ -49,10 +49,10 @@ import ( "k8s.io/client-go/util/workqueue" "k8s.io/component-base/metrics/prometheus/ratelimiter" v1helper "k8s.io/component-helpers/scheduling/corev1" + "k8s.io/component-helpers/scheduling/corev1/nodeaffinity" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/daemon/util" - pluginhelper "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" "k8s.io/utils/integer" ) @@ -1276,7 +1276,8 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *apps. // Predicates checks if a DaemonSet's pod can run on a node. func Predicates(pod *v1.Pod, node *v1.Node, taints []v1.Taint) (fitsNodeName, fitsNodeAffinity, fitsTaints bool) { fitsNodeName = len(pod.Spec.NodeName) == 0 || pod.Spec.NodeName == node.Name - fitsNodeAffinity = pluginhelper.PodMatchesNodeSelectorAndAffinityTerms(pod, node) + // Ignore parsing errors for backwards compatibility. + fitsNodeAffinity, _ = nodeaffinity.GetRequiredNodeAffinity(pod).Match(node) _, hasUntoleratedTaint := v1helper.FindMatchingUntoleratedTaint(taints, pod.Spec.Tolerations, func(t *v1.Taint) bool { return t.Effect == v1.TaintEffectNoExecute || t.Effect == v1.TaintEffectNoSchedule }) diff --git a/pkg/kubelet/lifecycle/predicate.go b/pkg/kubelet/lifecycle/predicate.go index 07b8792dc36..681c2b9adaf 100644 --- a/pkg/kubelet/lifecycle/predicate.go +++ b/pkg/kubelet/lifecycle/predicate.go @@ -20,11 +20,11 @@ import ( "fmt" v1 "k8s.io/api/core/v1" + v1affinityhelper "k8s.io/component-helpers/scheduling/corev1/nodeaffinity" "k8s.io/klog/v2" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/kubelet/util/format" schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework" - pluginhelper "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodename" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeports" @@ -236,7 +236,9 @@ func GeneralPredicates(pod *v1.Pod, nodeInfo *schedulerframework.NodeInfo) ([]Pr }) } - if !pluginhelper.PodMatchesNodeSelectorAndAffinityTerms(pod, nodeInfo.Node()) { + // Ignore parsing errors for backwards compatibility. + match, _ := v1affinityhelper.GetRequiredNodeAffinity(pod).Match(nodeInfo.Node()) + if !match { reasons = append(reasons, &PredicateFailureError{nodeaffinity.Name, nodeaffinity.ErrReasonPod}) } if !nodename.Fits(pod, nodeInfo) { diff --git a/pkg/scheduler/framework/plugins/helper/node_affinity.go b/pkg/scheduler/framework/plugins/helper/node_affinity.go deleted file mode 100644 index 29380e7dd11..00000000000 --- a/pkg/scheduler/framework/plugins/helper/node_affinity.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2019 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 helper - -import ( - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/component-helpers/scheduling/corev1" -) - -// PodMatchesNodeSelectorAndAffinityTerms checks whether the pod is schedulable onto nodes according to -// the requirements in both NodeAffinity and nodeSelector. -func PodMatchesNodeSelectorAndAffinityTerms(pod *v1.Pod, node *v1.Node) bool { - // Check if node.Labels match pod.Spec.NodeSelector. - if len(pod.Spec.NodeSelector) > 0 { - selector := labels.SelectorFromSet(pod.Spec.NodeSelector) - if !selector.Matches(labels.Set(node.Labels)) { - return false - } - } - if pod.Spec.Affinity == nil { - return true - } - return NodeMatchesNodeAffinity(pod.Spec.Affinity.NodeAffinity, node) -} - -// NodeMatchesNodeAffinity checks whether the Node satisfy the given NodeAffinity. -func NodeMatchesNodeAffinity(affinity *v1.NodeAffinity, node *v1.Node) bool { - // 1. nil NodeSelector matches all nodes (i.e. does not filter out any nodes) - // 2. nil []NodeSelectorTerm (equivalent to non-nil empty NodeSelector) matches no nodes - // 3. zero-length non-nil []NodeSelectorTerm matches no nodes also, just for simplicity - // 4. nil []NodeSelectorRequirement (equivalent to non-nil empty NodeSelectorTerm) matches no nodes - // 5. zero-length non-nil []NodeSelectorRequirement matches no nodes also, just for simplicity - // 6. non-nil empty NodeSelectorRequirement is not allowed - if affinity == nil { - return true - } - // Match node selector for requiredDuringSchedulingRequiredDuringExecution. - // TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution. - // if affinity.RequiredDuringSchedulingRequiredDuringExecution != nil && !nodeMatchesNodeSelector(node, affinity.RequiredDuringSchedulingRequiredDuringExecution) { - // return false - // } - - // Match node selector for requiredDuringSchedulingIgnoredDuringExecution. - if affinity.RequiredDuringSchedulingIgnoredDuringExecution != nil && !nodeMatchesNodeSelector(node, affinity.RequiredDuringSchedulingIgnoredDuringExecution) { - return false - } - return true -} - -// nodeMatchesNodeSelector checks if a node's labels satisfy a list of node selector terms, -// terms are ORed, and an empty list of terms will match nothing. -func nodeMatchesNodeSelector(node *v1.Node, nodeSelector *v1.NodeSelector) bool { - matches, _ := corev1.MatchNodeSelectorTerms(node, nodeSelector) - return matches -} diff --git a/pkg/scheduler/framework/plugins/helper/node_affinity_test.go b/pkg/scheduler/framework/plugins/helper/node_affinity_test.go deleted file mode 100644 index ac8000e66fc..00000000000 --- a/pkg/scheduler/framework/plugins/helper/node_affinity_test.go +++ /dev/null @@ -1,711 +0,0 @@ -/* -Copyright 2019 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 helper - -import ( - "testing" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestPodMatchesNodeSelectorAndAffinityTerms(t *testing.T) { - tests := []struct { - name string - pod *v1.Pod - labels map[string]string - nodeName string - want bool - }{ - { - name: "no selector", - pod: &v1.Pod{}, - want: true, - }, - { - name: "missing labels", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - }, - }, - want: false, - }, - { - name: "same labels", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "node labels are superset", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - want: true, - }, - { - name: "node labels are subset", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - }, - { - name: "Pod with matchExpressions using In operator that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"bar", "value2"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "Pod with matchExpressions using Gt operator that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "kernel-version", - Operator: v1.NodeSelectorOpGt, - Values: []string{"0204"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - // We use two digit to denote major version and two digit for minor version. - "kernel-version": "0206", - }, - want: true, - }, - { - name: "Pod with matchExpressions using NotIn operator that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "mem-type", - Operator: v1.NodeSelectorOpNotIn, - Values: []string{"DDR", "DDR2"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "mem-type": "DDR3", - }, - want: true, - }, - { - name: "Pod with matchExpressions using Exists operator that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "GPU", - Operator: v1.NodeSelectorOpExists, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "GPU": "NVIDIA-GRID-K1", - }, - want: true, - }, - { - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"value1", "value2"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - name: "Pod with affinity that don't match node's labels won't schedule onto the node", - }, - { - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: nil, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - name: "Pod with a nil []NodeSelectorTerm in affinity, can't match the node's labels and won't schedule onto the node", - }, - { - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{}, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - name: "Pod with an empty []NodeSelectorTerm in affinity, can't match the node's labels and won't schedule onto the node", - }, - { - name: "Pod with empty MatchExpressions is not a valid value will match no objects and won't schedule onto the node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{}, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - }, - { - name: "Pod with no Affinity will schedule onto a node", - pod: &v1.Pod{}, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "Pod with Affinity but nil NodeSelector will schedule onto a node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: nil, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "Pod with multiple matchExpressions ANDed that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "GPU", - Operator: v1.NodeSelectorOpExists, - }, { - Key: "GPU", - Operator: v1.NodeSelectorOpNotIn, - Values: []string{"AMD", "INTER"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "GPU": "NVIDIA-GRID-K1", - }, - want: true, - }, - { - name: "Pod with multiple matchExpressions ANDed that doesn't match the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "GPU", - Operator: v1.NodeSelectorOpExists, - }, { - Key: "GPU", - Operator: v1.NodeSelectorOpIn, - Values: []string{"AMD", "INTER"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "GPU": "NVIDIA-GRID-K1", - }, - want: false, - }, - { - name: "Pod with multiple NodeSelectorTerms ORed in affinity, matches the node's labels and will schedule onto the node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"bar", "value2"}, - }, - }, - }, - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "diffkey", - Operator: v1.NodeSelectorOpIn, - Values: []string{"wrong", "value2"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "Pod with an Affinity and a PodSpec.NodeSelector(the old thing that we are deprecating) " + - "both are satisfied, will schedule onto the node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpExists, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: true, - }, - { - name: "Pod with an Affinity matches node's labels but the PodSpec.NodeSelector(the old thing that we are deprecating) " + - "is not satisfied, won't schedule onto the node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpExists, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "barrrrrr", - }, - want: false, - }, - { - name: "Pod with an invalid value in Affinity term won't be scheduled onto the node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpNotIn, - Values: []string{"invalid value: ___@#$%^"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - labels: map[string]string{ - "foo": "bar", - }, - want: false, - }, - { - name: "Pod with matchFields using In operator that matches the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_1", - want: true, - }, - { - name: "Pod with matchFields using In operator that does not match the existing node", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_2", - want: false, - }, - { - name: "Pod with two terms: matchFields does not match, but matchExpressions matches", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - }, - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"bar"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_2", - labels: map[string]string{"foo": "bar"}, - want: true, - }, - { - name: "Pod with one term: matchFields does not match, but matchExpressions matches", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"bar"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_2", - labels: map[string]string{"foo": "bar"}, - want: false, - }, - { - name: "Pod with one term: both matchFields and matchExpressions match", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"bar"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_1", - labels: map[string]string{"foo": "bar"}, - want: true, - }, - { - name: "Pod with two terms: both matchFields and matchExpressions do not match", - pod: &v1.Pod{ - Spec: v1.PodSpec{ - Affinity: &v1.Affinity{ - NodeAffinity: &v1.NodeAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ - NodeSelectorTerms: []v1.NodeSelectorTerm{ - { - MatchFields: []v1.NodeSelectorRequirement{ - { - Key: metav1.ObjectNameField, - Operator: v1.NodeSelectorOpIn, - Values: []string{"node_1"}, - }, - }, - }, - { - MatchExpressions: []v1.NodeSelectorRequirement{ - { - Key: "foo", - Operator: v1.NodeSelectorOpIn, - Values: []string{"not-match-to-bar"}, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nodeName: "node_2", - labels: map[string]string{"foo": "bar"}, - want: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - node := v1.Node{ObjectMeta: metav1.ObjectMeta{ - Name: test.nodeName, - Labels: test.labels, - }} - got := PodMatchesNodeSelectorAndAffinityTerms(test.pod, &node) - if test.want != got { - t.Errorf("expected: %v got %v", test.want, got) - } - }) - } -}