mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #95531 from damemi/move-scheduler-helpers
Move MatchNodeSelectorTerms to k8s.io/component-helpers
This commit is contained in:
		@@ -12,7 +12,6 @@ go_test(
 | 
			
		||||
    embed = [":go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
			
		||||
@@ -27,10 +26,8 @@ go_library(
 | 
			
		||||
        "//pkg/apis/core/helper:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/selection:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,8 @@ import (
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/fields"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/selection"
 | 
			
		||||
	apierrors "k8s.io/apimachinery/pkg/util/errors"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/validation"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/apis/core/helper"
 | 
			
		||||
)
 | 
			
		||||
@@ -233,72 +231,6 @@ func containsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.Persisten
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
 | 
			
		||||
// labels.Selector.
 | 
			
		||||
func nodeSelectorRequirementsAsSelector(nsm []v1.NodeSelectorRequirement) (labels.Selector, error) {
 | 
			
		||||
	if len(nsm) == 0 {
 | 
			
		||||
		return labels.Nothing(), nil
 | 
			
		||||
	}
 | 
			
		||||
	selector := labels.NewSelector()
 | 
			
		||||
	for _, expr := range nsm {
 | 
			
		||||
		var op selection.Operator
 | 
			
		||||
		switch expr.Operator {
 | 
			
		||||
		case v1.NodeSelectorOpIn:
 | 
			
		||||
			op = selection.In
 | 
			
		||||
		case v1.NodeSelectorOpNotIn:
 | 
			
		||||
			op = selection.NotIn
 | 
			
		||||
		case v1.NodeSelectorOpExists:
 | 
			
		||||
			op = selection.Exists
 | 
			
		||||
		case v1.NodeSelectorOpDoesNotExist:
 | 
			
		||||
			op = selection.DoesNotExist
 | 
			
		||||
		case v1.NodeSelectorOpGt:
 | 
			
		||||
			op = selection.GreaterThan
 | 
			
		||||
		case v1.NodeSelectorOpLt:
 | 
			
		||||
			op = selection.LessThan
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
 | 
			
		||||
		}
 | 
			
		||||
		r, err := labels.NewRequirement(expr.Key, op, expr.Values)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		selector = selector.Add(*r)
 | 
			
		||||
	}
 | 
			
		||||
	return selector, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nodeSelectorRequirementsAsFieldSelector converts the []NodeSelectorRequirement core type into a struct that implements
 | 
			
		||||
// fields.Selector.
 | 
			
		||||
func nodeSelectorRequirementsAsFieldSelector(nsm []v1.NodeSelectorRequirement) (fields.Selector, error) {
 | 
			
		||||
	if len(nsm) == 0 {
 | 
			
		||||
		return fields.Nothing(), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	selectors := []fields.Selector{}
 | 
			
		||||
	for _, expr := range nsm {
 | 
			
		||||
		switch expr.Operator {
 | 
			
		||||
		case v1.NodeSelectorOpIn:
 | 
			
		||||
			if len(expr.Values) != 1 {
 | 
			
		||||
				return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q",
 | 
			
		||||
					len(expr.Values), expr.Operator)
 | 
			
		||||
			}
 | 
			
		||||
			selectors = append(selectors, fields.OneTermEqualSelector(expr.Key, expr.Values[0]))
 | 
			
		||||
 | 
			
		||||
		case v1.NodeSelectorOpNotIn:
 | 
			
		||||
			if len(expr.Values) != 1 {
 | 
			
		||||
				return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q",
 | 
			
		||||
					len(expr.Values), expr.Operator)
 | 
			
		||||
			}
 | 
			
		||||
			selectors = append(selectors, fields.OneTermNotEqualSelector(expr.Key, expr.Values[0]))
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, fmt.Errorf("%q is not a valid node field selector operator", expr.Operator)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fields.AndSelectors(selectors...), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NodeSelectorRequirementKeysExistInNodeSelectorTerms checks if a NodeSelectorTerm with key is already specified in terms
 | 
			
		||||
func NodeSelectorRequirementKeysExistInNodeSelectorTerms(reqs []v1.NodeSelectorRequirement, terms []v1.NodeSelectorTerm) bool {
 | 
			
		||||
	for _, req := range reqs {
 | 
			
		||||
@@ -313,50 +245,6 @@ func NodeSelectorRequirementKeysExistInNodeSelectorTerms(reqs []v1.NodeSelectorR
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MatchNodeSelectorTerms checks whether the node labels and fields match node selector terms in ORed;
 | 
			
		||||
// nil or empty term matches no objects.
 | 
			
		||||
func MatchNodeSelectorTerms(
 | 
			
		||||
	node *v1.Node,
 | 
			
		||||
	nodeSelector *v1.NodeSelector,
 | 
			
		||||
) (bool, error) {
 | 
			
		||||
	if node == nil {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	var errors []error
 | 
			
		||||
	for _, req := range nodeSelector.NodeSelectorTerms {
 | 
			
		||||
		// nil or empty term selects no objects
 | 
			
		||||
		if len(req.MatchExpressions) == 0 && len(req.MatchFields) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(req.MatchExpressions) != 0 {
 | 
			
		||||
			labelSelector, err := nodeSelectorRequirementsAsSelector(req.MatchExpressions)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errors = append(errors, err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if labelSelector == nil || !labelSelector.Matches(labels.Set(node.Labels)) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(req.MatchFields) != 0 && len(node.Name) > 0 {
 | 
			
		||||
			fieldSelector, err := nodeSelectorRequirementsAsFieldSelector(req.MatchFields)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errors = append(errors, err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if fieldSelector == nil || !fieldSelector.Matches(fields.Set{"metadata.name": node.Name}) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false, apierrors.NewAggregate(errors)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TopologySelectorRequirementsAsSelector converts the []TopologySelectorLabelRequirement api type into a struct
 | 
			
		||||
// that implements labels.Selector.
 | 
			
		||||
func TopologySelectorRequirementsAsSelector(tsm []v1.TopologySelectorLabelRequirement) (labels.Selector, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@ import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
@@ -246,70 +245,6 @@ func TestRemoveDuplicateAccessModes(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
 | 
			
		||||
	matchExpressions := []v1.NodeSelectorRequirement{{
 | 
			
		||||
		Key:      "foo",
 | 
			
		||||
		Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
		Values:   []string{"bar", "baz"},
 | 
			
		||||
	}}
 | 
			
		||||
	mustParse := func(s string) labels.Selector {
 | 
			
		||||
		out, e := labels.Parse(s)
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			panic(e)
 | 
			
		||||
		}
 | 
			
		||||
		return out
 | 
			
		||||
	}
 | 
			
		||||
	tc := []struct {
 | 
			
		||||
		in        []v1.NodeSelectorRequirement
 | 
			
		||||
		out       labels.Selector
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{in: nil, out: labels.Nothing()},
 | 
			
		||||
		{in: []v1.NodeSelectorRequirement{}, out: labels.Nothing()},
 | 
			
		||||
		{
 | 
			
		||||
			in:  matchExpressions,
 | 
			
		||||
			out: mustParse("foo in (baz,bar)"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "foo",
 | 
			
		||||
				Operator: v1.NodeSelectorOpExists,
 | 
			
		||||
				Values:   []string{"bar", "baz"},
 | 
			
		||||
			}},
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "foo",
 | 
			
		||||
				Operator: v1.NodeSelectorOpGt,
 | 
			
		||||
				Values:   []string{"1"},
 | 
			
		||||
			}},
 | 
			
		||||
			out: mustParse("foo>1"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "bar",
 | 
			
		||||
				Operator: v1.NodeSelectorOpLt,
 | 
			
		||||
				Values:   []string{"7"},
 | 
			
		||||
			}},
 | 
			
		||||
			out: mustParse("bar<7"),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range tc {
 | 
			
		||||
		out, err := nodeSelectorRequirementsAsSelector(tc.in)
 | 
			
		||||
		if err == nil && tc.expectErr {
 | 
			
		||||
			t.Errorf("[%v]expected error but got none.", i)
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil && !tc.expectErr {
 | 
			
		||||
			t.Errorf("[%v]did not expect error but got: %v", i, err)
 | 
			
		||||
		}
 | 
			
		||||
		if !reflect.DeepEqual(out, tc.out) {
 | 
			
		||||
			t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTopologySelectorRequirementsAsSelector(t *testing.T) {
 | 
			
		||||
	mustParse := func(s string) labels.Selector {
 | 
			
		||||
		out, e := labels.Parse(s)
 | 
			
		||||
@@ -591,492 +526,6 @@ func TestGetAvoidPodsFromNode(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMatchNodeSelectorTerms(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		nodeSelector *v1.NodeSelector
 | 
			
		||||
		node         *v1.Node
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args args
 | 
			
		||||
		want bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "nil terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: nil,
 | 
			
		||||
				node:         nil,
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "node label matches matchExpressions terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "node field matches matchFields terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid node field requirement",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1, host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "fieldSelectorTerm with node labels",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "not_host_1", Labels: map[string]string{
 | 
			
		||||
					"metadata.name": "host_1",
 | 
			
		||||
				}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm with node fields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, but only node fields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (both matched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (one mismatched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val-failed",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "multi-selector was set, both node fields and labels (one mismatched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val-failed",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got, _ := MatchNodeSelectorTerms(tt.args.node, tt.args.nodeSelector); got != tt.want {
 | 
			
		||||
				t.Errorf("MatchNodeSelectorTermsORed() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TestMatchNodeSelectorTermsStateless ensures MatchNodeSelectorTerms()
 | 
			
		||||
// is invoked in a "stateless" manner, i.e. nodeSelector should NOT
 | 
			
		||||
// be deeply modified after invoking
 | 
			
		||||
func TestMatchNodeSelectorTermsStateless(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		nodeSelector *v1.NodeSelector
 | 
			
		||||
		node         *v1.Node
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args args
 | 
			
		||||
		want *v1.NodeSelector
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "nil terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: nil,
 | 
			
		||||
				node:         nil,
 | 
			
		||||
			},
 | 
			
		||||
			want: nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels: preordered matchExpressions and nil matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels: unordered matchExpressions and nil matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeFields: nil matchExpressions and preordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeFields: nil matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: ordered matchExpressions and ordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: ordered matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: unordered matchExpressions and ordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: unordered matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			MatchNodeSelectorTerms(tt.args.node, tt.args.nodeSelector)
 | 
			
		||||
			if !apiequality.Semantic.DeepEqual(tt.args.nodeSelector, tt.want) {
 | 
			
		||||
				// fail when tt.args.nodeSelector is deeply modified
 | 
			
		||||
				t.Errorf("MatchNodeSelectorTerms() got = %v, want %v", tt.args.nodeSelector, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMatchTopologySelectorTerms(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		topologySelectorTerms []v1.TopologySelectorTerm
 | 
			
		||||
 
 | 
			
		||||
@@ -10,13 +10,13 @@ go_library(
 | 
			
		||||
    importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper",
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/apis/core/v1/helper:go_default_library",
 | 
			
		||||
        "//pkg/scheduler/framework:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-helpers/scheduling/corev1:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ package helper
 | 
			
		||||
import (
 | 
			
		||||
	"k8s.io/api/core/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
 | 
			
		||||
	"k8s.io/component-helpers/scheduling/corev1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PodMatchesNodeSelectorAndAffinityTerms checks whether the pod is schedulable onto nodes according to
 | 
			
		||||
@@ -71,6 +71,6 @@ func PodMatchesNodeSelectorAndAffinityTerms(pod *v1.Pod, node *v1.Node) bool {
 | 
			
		||||
// terms are ORed, and an empty list of terms will match nothing.
 | 
			
		||||
func nodeMatchesNodeSelectorTerms(node *v1.Node, nodeSelector *v1.NodeSelector) bool {
 | 
			
		||||
	// TODO(@alculquicondor, #95738): parse this error earlier in the plugin so we only need to do it once per pod
 | 
			
		||||
	matches, _ := v1helper.MatchNodeSelectorTerms(node, nodeSelector)
 | 
			
		||||
	matches, _ := corev1.MatchNodeSelectorTerms(node, nodeSelector)
 | 
			
		||||
	return matches
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,11 @@ go_library(
 | 
			
		||||
    importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodeaffinity",
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/apis/core/v1/helper:go_default_library",
 | 
			
		||||
        "//pkg/scheduler/framework:go_default_library",
 | 
			
		||||
        "//pkg/scheduler/framework/plugins/helper:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-helpers/scheduling/corev1:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
 | 
			
		||||
	"k8s.io/component-helpers/scheduling/corev1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/scheduler/framework"
 | 
			
		||||
	pluginhelper "k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper"
 | 
			
		||||
)
 | 
			
		||||
@@ -87,7 +87,7 @@ func (pl *NodeAffinity) Score(ctx context.Context, state *framework.CycleState,
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO: Avoid computing it for all nodes if this becomes a performance problem.
 | 
			
		||||
			matches, err := v1helper.MatchNodeSelectorTerms(node, &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{preferredSchedulingTerm.Preference}})
 | 
			
		||||
			matches, err := corev1.MatchNodeSelectorTerms(node, &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{preferredSchedulingTerm.Preference}})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0, framework.AsStatus(err)
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ go_library(
 | 
			
		||||
        "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-base/metrics:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-helpers/scheduling/corev1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/mount-utils:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/klog/v2:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/utils/exec:go_default_library",
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/component-helpers/scheduling/corev1"
 | 
			
		||||
	"k8s.io/klog/v2"
 | 
			
		||||
	"k8s.io/mount-utils"
 | 
			
		||||
	utilexec "k8s.io/utils/exec"
 | 
			
		||||
@@ -175,7 +176,7 @@ func checkVolumeNodeAffinity(pv *v1.PersistentVolume, node *v1.Node) error {
 | 
			
		||||
	if pv.Spec.NodeAffinity.Required != nil {
 | 
			
		||||
		terms := pv.Spec.NodeAffinity.Required
 | 
			
		||||
		klog.V(10).Infof("Match for Required node selector terms %+v", terms)
 | 
			
		||||
		if matches, err := v1helper.MatchNodeSelectorTerms(node, terms); err != nil {
 | 
			
		||||
		if matches, err := corev1.MatchNodeSelectorTerms(node, terms); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if !matches {
 | 
			
		||||
			return fmt.Errorf("no matching NodeSelectorTerms")
 | 
			
		||||
 
 | 
			
		||||
@@ -9,14 +9,25 @@ go_library(
 | 
			
		||||
    importmap = "k8s.io/kubernetes/vendor/k8s.io/component-helpers/scheduling/corev1",
 | 
			
		||||
    importpath = "k8s.io/component-helpers/scheduling/corev1",
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/selection:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go_test(
 | 
			
		||||
    name = "go_default_test",
 | 
			
		||||
    srcs = ["helpers_test.go"],
 | 
			
		||||
    embed = [":go_default_library"],
 | 
			
		||||
    deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,13 @@ limitations under the License.
 | 
			
		||||
package corev1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/fields"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/selection"
 | 
			
		||||
	apierrors "k8s.io/apimachinery/pkg/util/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PodPriority returns priority of the given pod.
 | 
			
		||||
@@ -30,3 +36,113 @@ func PodPriority(pod *v1.Pod) int32 {
 | 
			
		||||
	// name of the pod was empty. So, we resolve to the static default priority.
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MatchNodeSelectorTerms checks whether the node labels and fields match node selector terms in ORed;
 | 
			
		||||
// nil or empty term matches no objects.
 | 
			
		||||
func MatchNodeSelectorTerms(
 | 
			
		||||
	node *v1.Node,
 | 
			
		||||
	nodeSelector *v1.NodeSelector,
 | 
			
		||||
) (bool, error) {
 | 
			
		||||
	if node == nil {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	var errors []error
 | 
			
		||||
	for _, req := range nodeSelector.NodeSelectorTerms {
 | 
			
		||||
		// nil or empty term selects no objects
 | 
			
		||||
		if len(req.MatchExpressions) == 0 && len(req.MatchFields) == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(req.MatchExpressions) != 0 {
 | 
			
		||||
			labelSelector, err := nodeSelectorRequirementsAsSelector(req.MatchExpressions)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errors = append(errors, err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if labelSelector == nil || !labelSelector.Matches(labels.Set(node.Labels)) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(req.MatchFields) != 0 && len(node.Name) > 0 {
 | 
			
		||||
			fieldSelector, err := nodeSelectorRequirementsAsFieldSelector(req.MatchFields)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errors = append(errors, err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if fieldSelector == nil || !fieldSelector.Matches(fields.Set{"metadata.name": node.Name}) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false, apierrors.NewAggregate(errors)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
 | 
			
		||||
// labels.Selector.
 | 
			
		||||
func nodeSelectorRequirementsAsSelector(nsm []v1.NodeSelectorRequirement) (labels.Selector, error) {
 | 
			
		||||
	if len(nsm) == 0 {
 | 
			
		||||
		return labels.Nothing(), nil
 | 
			
		||||
	}
 | 
			
		||||
	selector := labels.NewSelector()
 | 
			
		||||
	for _, expr := range nsm {
 | 
			
		||||
		var op selection.Operator
 | 
			
		||||
		switch expr.Operator {
 | 
			
		||||
		case v1.NodeSelectorOpIn:
 | 
			
		||||
			op = selection.In
 | 
			
		||||
		case v1.NodeSelectorOpNotIn:
 | 
			
		||||
			op = selection.NotIn
 | 
			
		||||
		case v1.NodeSelectorOpExists:
 | 
			
		||||
			op = selection.Exists
 | 
			
		||||
		case v1.NodeSelectorOpDoesNotExist:
 | 
			
		||||
			op = selection.DoesNotExist
 | 
			
		||||
		case v1.NodeSelectorOpGt:
 | 
			
		||||
			op = selection.GreaterThan
 | 
			
		||||
		case v1.NodeSelectorOpLt:
 | 
			
		||||
			op = selection.LessThan
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
 | 
			
		||||
		}
 | 
			
		||||
		r, err := labels.NewRequirement(expr.Key, op, expr.Values)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		selector = selector.Add(*r)
 | 
			
		||||
	}
 | 
			
		||||
	return selector, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nodeSelectorRequirementsAsFieldSelector converts the []NodeSelectorRequirement core type into a struct that implements
 | 
			
		||||
// fields.Selector.
 | 
			
		||||
func nodeSelectorRequirementsAsFieldSelector(nsm []v1.NodeSelectorRequirement) (fields.Selector, error) {
 | 
			
		||||
	if len(nsm) == 0 {
 | 
			
		||||
		return fields.Nothing(), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	selectors := []fields.Selector{}
 | 
			
		||||
	for _, expr := range nsm {
 | 
			
		||||
		switch expr.Operator {
 | 
			
		||||
		case v1.NodeSelectorOpIn:
 | 
			
		||||
			if len(expr.Values) != 1 {
 | 
			
		||||
				return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q",
 | 
			
		||||
					len(expr.Values), expr.Operator)
 | 
			
		||||
			}
 | 
			
		||||
			selectors = append(selectors, fields.OneTermEqualSelector(expr.Key, expr.Values[0]))
 | 
			
		||||
 | 
			
		||||
		case v1.NodeSelectorOpNotIn:
 | 
			
		||||
			if len(expr.Values) != 1 {
 | 
			
		||||
				return nil, fmt.Errorf("unexpected number of value (%d) for node field selector operator %q",
 | 
			
		||||
					len(expr.Values), expr.Operator)
 | 
			
		||||
			}
 | 
			
		||||
			selectors = append(selectors, fields.OneTermNotEqualSelector(expr.Key, expr.Values[0]))
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, fmt.Errorf("%q is not a valid node field selector operator", expr.Operator)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fields.AndSelectors(selectors...), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,13 @@ limitations under the License.
 | 
			
		||||
package corev1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TestPodPriority tests PodPriority function.
 | 
			
		||||
@@ -57,3 +61,553 @@ func TestPodPriority(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMatchNodeSelectorTerms(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		nodeSelector *v1.NodeSelector
 | 
			
		||||
		node         *v1.Node
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args args
 | 
			
		||||
		want bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "nil terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: nil,
 | 
			
		||||
				node:         nil,
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "node label matches matchExpressions terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "node field matches matchFields terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid node field requirement",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1, host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "fieldSelectorTerm with node labels",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "not_host_1", Labels: map[string]string{
 | 
			
		||||
					"metadata.name": "host_1",
 | 
			
		||||
				}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm with node fields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, but only node fields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (both matched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "labelSelectorTerm and fieldSelectorTerm was set, both node fields and labels (one mismatched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val-failed",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "multi-selector was set, both node fields and labels (one mismatched)",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val-failed",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			if got, _ := MatchNodeSelectorTerms(tt.args.node, tt.args.nodeSelector); got != tt.want {
 | 
			
		||||
				t.Errorf("MatchNodeSelectorTermsORed() = %v, want %v", got, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TestMatchNodeSelectorTermsStateless ensures MatchNodeSelectorTerms()
 | 
			
		||||
// is invoked in a "stateless" manner, i.e. nodeSelector should NOT
 | 
			
		||||
// be deeply modified after invoking
 | 
			
		||||
func TestMatchNodeSelectorTermsStateless(t *testing.T) {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		nodeSelector *v1.NodeSelector
 | 
			
		||||
		node         *v1.Node
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args args
 | 
			
		||||
		want *v1.NodeSelector
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "nil terms",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: nil,
 | 
			
		||||
				node:         nil,
 | 
			
		||||
			},
 | 
			
		||||
			want: nil,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels: preordered matchExpressions and nil matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels: unordered matchExpressions and nil matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"label_1": "label_1_val"}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeFields: nil matchExpressions and preordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeFields: nil matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1"}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: ordered matchExpressions and ordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: ordered matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_1_val", "label_2_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: unordered matchExpressions and ordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_1", "host_2"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_1", "host_2"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "nodeLabels and nodeFields: unordered matchExpressions and unordered matchFields",
 | 
			
		||||
			args: args{
 | 
			
		||||
				nodeSelector: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "label_1",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
						}},
 | 
			
		||||
						MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
							Key:      "metadata.name",
 | 
			
		||||
							Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
							Values:   []string{"host_2", "host_1"},
 | 
			
		||||
						}},
 | 
			
		||||
					},
 | 
			
		||||
				}},
 | 
			
		||||
				node: &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "host_1",
 | 
			
		||||
					Labels: map[string]string{
 | 
			
		||||
						"label_1": "label_1_val",
 | 
			
		||||
					}}},
 | 
			
		||||
			},
 | 
			
		||||
			want: &v1.NodeSelector{NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
				{
 | 
			
		||||
					MatchExpressions: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "label_1",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"label_2_val", "label_1_val"},
 | 
			
		||||
					}},
 | 
			
		||||
					MatchFields: []v1.NodeSelectorRequirement{{
 | 
			
		||||
						Key:      "metadata.name",
 | 
			
		||||
						Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
						Values:   []string{"host_2", "host_1"},
 | 
			
		||||
					}},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			MatchNodeSelectorTerms(tt.args.node, tt.args.nodeSelector)
 | 
			
		||||
			if !apiequality.Semantic.DeepEqual(tt.args.nodeSelector, tt.want) {
 | 
			
		||||
				// fail when tt.args.nodeSelector is deeply modified
 | 
			
		||||
				t.Errorf("MatchNodeSelectorTerms() got = %v, want %v", tt.args.nodeSelector, tt.want)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
 | 
			
		||||
	matchExpressions := []v1.NodeSelectorRequirement{{
 | 
			
		||||
		Key:      "foo",
 | 
			
		||||
		Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
		Values:   []string{"bar", "baz"},
 | 
			
		||||
	}}
 | 
			
		||||
	mustParse := func(s string) labels.Selector {
 | 
			
		||||
		out, e := labels.Parse(s)
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			panic(e)
 | 
			
		||||
		}
 | 
			
		||||
		return out
 | 
			
		||||
	}
 | 
			
		||||
	tc := []struct {
 | 
			
		||||
		in        []v1.NodeSelectorRequirement
 | 
			
		||||
		out       labels.Selector
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{in: nil, out: labels.Nothing()},
 | 
			
		||||
		{in: []v1.NodeSelectorRequirement{}, out: labels.Nothing()},
 | 
			
		||||
		{
 | 
			
		||||
			in:  matchExpressions,
 | 
			
		||||
			out: mustParse("foo in (baz,bar)"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "foo",
 | 
			
		||||
				Operator: v1.NodeSelectorOpExists,
 | 
			
		||||
				Values:   []string{"bar", "baz"},
 | 
			
		||||
			}},
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "foo",
 | 
			
		||||
				Operator: v1.NodeSelectorOpGt,
 | 
			
		||||
				Values:   []string{"1"},
 | 
			
		||||
			}},
 | 
			
		||||
			out: mustParse("foo>1"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			in: []v1.NodeSelectorRequirement{{
 | 
			
		||||
				Key:      "bar",
 | 
			
		||||
				Operator: v1.NodeSelectorOpLt,
 | 
			
		||||
				Values:   []string{"7"},
 | 
			
		||||
			}},
 | 
			
		||||
			out: mustParse("bar<7"),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range tc {
 | 
			
		||||
		out, err := nodeSelectorRequirementsAsSelector(tc.in)
 | 
			
		||||
		if err == nil && tc.expectErr {
 | 
			
		||||
			t.Errorf("[%v]expected error but got none.", i)
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil && !tc.expectErr {
 | 
			
		||||
			t.Errorf("[%v]did not expect error but got: %v", i, err)
 | 
			
		||||
		}
 | 
			
		||||
		if !reflect.DeepEqual(out, tc.out) {
 | 
			
		||||
			t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user