mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Cleanup work to enable feature gating annotations
This commit is contained in:
		@@ -27,9 +27,7 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/features"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
 | 
			
		||||
@@ -281,7 +279,8 @@ const (
 | 
			
		||||
	ObjectTTLAnnotationKey string = "node.alpha.kubernetes.io/ttl"
 | 
			
		||||
 | 
			
		||||
	// AffinityAnnotationKey represents the key of affinity data (json serialized)
 | 
			
		||||
	// in the Annotations of a Pod.  TODO remove in 1.7
 | 
			
		||||
	// in the Annotations of a Pod.
 | 
			
		||||
	// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
	AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -606,7 +605,7 @@ func RemoveTaint(node *Node, taint *Taint) (*Node, bool, error) {
 | 
			
		||||
 | 
			
		||||
// GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations
 | 
			
		||||
// and converts it to the Affinity type in api.
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
 | 
			
		||||
	if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
 | 
			
		||||
		var affinity Affinity
 | 
			
		||||
@@ -618,26 +617,3 @@ func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, er
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reconcile api and annotation affinity definitions.
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
func ReconcileAffinity(pod *Pod) *Affinity {
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	if utilfeature.DefaultFeatureGate.Enabled(features.AffinityInAnnotations) {
 | 
			
		||||
		annotationsAffinity, _ := GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
		if affinity == nil && annotationsAffinity != nil {
 | 
			
		||||
			affinity = annotationsAffinity
 | 
			
		||||
		} else if annotationsAffinity != nil {
 | 
			
		||||
			if affinity != nil && affinity.NodeAffinity == nil && annotationsAffinity.NodeAffinity != nil {
 | 
			
		||||
				affinity.NodeAffinity = annotationsAffinity.NodeAffinity
 | 
			
		||||
			}
 | 
			
		||||
			if affinity != nil && affinity.PodAffinity == nil && annotationsAffinity.PodAffinity != nil {
 | 
			
		||||
				affinity.PodAffinity = annotationsAffinity.PodAffinity
 | 
			
		||||
			}
 | 
			
		||||
			if affinity != nil && affinity.PodAntiAffinity == nil && annotationsAffinity.PodAntiAffinity != nil {
 | 
			
		||||
				affinity.PodAntiAffinity = annotationsAffinity.PodAntiAffinity
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return affinity
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,14 +17,12 @@ limitations under the License.
 | 
			
		||||
package v1
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/labels"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestAddToNodeAddresses(t *testing.T) {
 | 
			
		||||
@@ -647,6 +645,7 @@ func TestSysctlsFromPodAnnotation(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestGetAffinityFromPodAnnotations(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		pod       *Pod
 | 
			
		||||
@@ -702,124 +701,3 @@ func TestGetAffinityFromPodAnnotations(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReconcileAffinity(t *testing.T) {
 | 
			
		||||
	baseAffinity := &Affinity{
 | 
			
		||||
		NodeAffinity: &NodeAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: &NodeSelector{
 | 
			
		||||
				NodeSelectorTerms: []NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []NodeSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "foo",
 | 
			
		||||
								Operator: NodeSelectorOpIn,
 | 
			
		||||
								Values:   []string{"bar", "value2"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PodAffinity: &PodAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "security",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
								Values:   []string{"securityscan"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "topologyKey1",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PodAntiAffinity: &PodAntiAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "service",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
								Values:   []string{"S1", "value2"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "topologyKey2",
 | 
			
		||||
					Namespaces:  []string{"ns1"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nodeAffinityAnnotation := map[string]string{
 | 
			
		||||
		AffinityAnnotationKey: `
 | 
			
		||||
		{"nodeAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [
 | 
			
		||||
			{
 | 
			
		||||
				"weight": 2,
 | 
			
		||||
				"preference": {"matchExpressions": [
 | 
			
		||||
					{
 | 
			
		||||
						"key": "foo",
 | 
			
		||||
						"operator": "In", "values": ["bar"]
 | 
			
		||||
					}
 | 
			
		||||
				]}
 | 
			
		||||
			}
 | 
			
		||||
		]}}`,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		pod                *Pod
 | 
			
		||||
		expected           *Affinity
 | 
			
		||||
		annotationsEnabled bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pod: &Pod{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Annotations: nodeAffinityAnnotation,
 | 
			
		||||
				},
 | 
			
		||||
				Spec: PodSpec{
 | 
			
		||||
					Affinity: baseAffinity,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected:           baseAffinity,
 | 
			
		||||
			annotationsEnabled: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &Pod{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Annotations: nodeAffinityAnnotation,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: &Affinity{
 | 
			
		||||
				NodeAffinity: &NodeAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []PreferredSchedulingTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 2,
 | 
			
		||||
							Preference: NodeSelectorTerm{
 | 
			
		||||
								MatchExpressions: []NodeSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "foo",
 | 
			
		||||
										Operator: NodeSelectorOpIn,
 | 
			
		||||
										Values:   []string{"bar"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			annotationsEnabled: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range testCases {
 | 
			
		||||
		utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("AffinityInAnnotations=%t", tc.annotationsEnabled))
 | 
			
		||||
		affinity := ReconcileAffinity(tc.pod)
 | 
			
		||||
		if affinity != tc.expected {
 | 
			
		||||
			t.Errorf("[%v]did not get expected affinity. got: %v instead of %v", i, affinity, tc.expected)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,11 @@ const (
 | 
			
		||||
	// Note: This feature is not supported for `BestEffort` pods.
 | 
			
		||||
	ExperimentalCriticalPodAnnotation utilfeature.Feature = "ExperimentalCriticalPodAnnotation"
 | 
			
		||||
 | 
			
		||||
	// Determines if affinity defined in annotations should bep rocessed
 | 
			
		||||
	// owner: @davidopp
 | 
			
		||||
	// alpha: v1.6
 | 
			
		||||
	//
 | 
			
		||||
	// Determines if affinity defined in annotations should be processed
 | 
			
		||||
	// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
	AffinityInAnnotations utilfeature.Feature = "AffinityInAnnotations"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ go_test(
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/api/resource",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/labels",
 | 
			
		||||
        "//vendor:k8s.io/apiserver/pkg/util/feature",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -585,7 +585,7 @@ func podMatchesNodeLabels(pod *v1.Pod, node *v1.Node) bool {
 | 
			
		||||
	// 5. zero-length non-nil []NodeSelectorRequirement matches no nodes also, just for simplicity
 | 
			
		||||
	// 6. non-nil empty NodeSelectorRequirement is not allowed
 | 
			
		||||
	nodeAffinityMatches := true
 | 
			
		||||
	affinity := v1.ReconcileAffinity(pod)
 | 
			
		||||
	affinity := schedulercache.ReconcileAffinity(pod)
 | 
			
		||||
	if affinity != nil && affinity.NodeAffinity != nil {
 | 
			
		||||
		nodeAffinity := affinity.NodeAffinity
 | 
			
		||||
		// if no required NodeAffinity requirements, will do no-op, means select all nodes.
 | 
			
		||||
@@ -897,7 +897,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta interface
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now check if <pod> requirements will be satisfied on this node.
 | 
			
		||||
	affinity := v1.ReconcileAffinity(pod)
 | 
			
		||||
	affinity := schedulercache.ReconcileAffinity(pod)
 | 
			
		||||
	if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) {
 | 
			
		||||
		return true, nil, nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -1001,7 +1001,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler
 | 
			
		||||
		}
 | 
			
		||||
		var nodeResult []matchingPodAntiAffinityTerm
 | 
			
		||||
		for _, existingPod := range nodeInfo.PodsWithAffinity() {
 | 
			
		||||
			affinity := v1.ReconcileAffinity(existingPod)
 | 
			
		||||
			affinity := schedulercache.ReconcileAffinity(existingPod)
 | 
			
		||||
			if affinity == nil {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
@@ -1029,7 +1029,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler
 | 
			
		||||
func (c *PodAffinityChecker) getMatchingAntiAffinityTerms(pod *v1.Pod, allPods []*v1.Pod) ([]matchingPodAntiAffinityTerm, error) {
 | 
			
		||||
	var result []matchingPodAntiAffinityTerm
 | 
			
		||||
	for _, existingPod := range allPods {
 | 
			
		||||
		affinity := v1.ReconcileAffinity(existingPod)
 | 
			
		||||
		affinity := schedulercache.ReconcileAffinity(existingPod)
 | 
			
		||||
		if affinity != nil && affinity.PodAntiAffinity != nil {
 | 
			
		||||
			existingPodNode, err := c.info.GetNodeInfo(existingPod.Spec.NodeName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -3581,7 +3581,7 @@ func TestVolumeZonePredicate(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestPodAnnotationFitsSelector(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
@@ -4000,7 +4000,7 @@ func TestPodAnnotationFitsSelector(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestInterPodAffinityAnnotations(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	podLabel := map[string]string{"service": "securityscan"}
 | 
			
		||||
@@ -4555,7 +4555,7 @@ func TestInterPodAffinityAnnotations(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestInterPodAffinityAnnotationsWithMultipleNodes(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	podLabelA := map[string]string{
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ go_test(
 | 
			
		||||
        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/api/resource",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
        "//vendor:k8s.io/apiserver/pkg/util/feature",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ func (p *podAffinityPriorityMap) processTerms(terms []v1.WeightedPodAffinityTerm
 | 
			
		||||
// Symmetry need to be considered for preferredDuringSchedulingIgnoredDuringExecution from podAffinity & podAntiAffinity,
 | 
			
		||||
// symmetry need to be considered for hard requirements from podAffinity
 | 
			
		||||
func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) {
 | 
			
		||||
	affinity := v1.ReconcileAffinity(pod)
 | 
			
		||||
	affinity := schedulercache.ReconcileAffinity(pod)
 | 
			
		||||
	hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil
 | 
			
		||||
	hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil
 | 
			
		||||
 | 
			
		||||
@@ -137,7 +137,7 @@ func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, node
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		existingPodAffinity := v1.ReconcileAffinity(existingPod)
 | 
			
		||||
		existingPodAffinity := schedulercache.ReconcileAffinity(existingPod)
 | 
			
		||||
		existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil
 | 
			
		||||
		existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -615,7 +615,7 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestInterPodAffinityAnnotationsPriority(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	labelRgChina := map[string]string{
 | 
			
		||||
@@ -1089,7 +1089,7 @@ func TestInterPodAffinityAnnotationsPriority(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO remove for 1.7
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestHardPodAffinityAnnotationsSymmetricWeight(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	podLabelServiceS1 := map[string]string{
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,6 @@ func PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.Nod
 | 
			
		||||
	return &priorityMetadata{
 | 
			
		||||
		nonZeroRequest: getNonZeroRequests(pod),
 | 
			
		||||
		podTolerations: tolerations,
 | 
			
		||||
		affinity:       v1.ReconcileAffinity(pod),
 | 
			
		||||
		affinity:       schedulercache.ReconcileAffinity(pod),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ func CalculateNodeAffinityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *s
 | 
			
		||||
		affinity = priorityMeta.affinity
 | 
			
		||||
	} else {
 | 
			
		||||
		// We couldn't parse metadata - fallback to the podspec.
 | 
			
		||||
		affinity = v1.ReconcileAffinity(pod)
 | 
			
		||||
		affinity = schedulercache.ReconcileAffinity(pod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var count int32
 | 
			
		||||
 
 | 
			
		||||
@@ -179,6 +179,7 @@ func TestNodeAffinityPriority(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestNodeAffinityAnnotationsPriority(t *testing.T) {
 | 
			
		||||
	utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=true")
 | 
			
		||||
	label1 := map[string]string{"foo": "bar"}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,23 +14,29 @@ go_library(
 | 
			
		||||
        "cache.go",
 | 
			
		||||
        "interface.go",
 | 
			
		||||
        "node_info.go",
 | 
			
		||||
        "reconcile_affinity.go",
 | 
			
		||||
        "util.go",
 | 
			
		||||
    ],
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/api/v1:go_default_library",
 | 
			
		||||
        "//pkg/features:go_default_library",
 | 
			
		||||
        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
			
		||||
        "//vendor:github.com/golang/glog",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/api/resource",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/labels",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
			
		||||
        "//vendor:k8s.io/apiserver/pkg/util/feature",
 | 
			
		||||
        "//vendor:k8s.io/client-go/tools/cache",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go_test(
 | 
			
		||||
    name = "go_default_test",
 | 
			
		||||
    srcs = ["cache_test.go"],
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "cache_test.go",
 | 
			
		||||
        "reconcile_affinity_test.go",
 | 
			
		||||
    ],
 | 
			
		||||
    library = ":go_default_library",
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    deps = [
 | 
			
		||||
@@ -39,6 +45,7 @@ go_test(
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/api/resource",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/labels",
 | 
			
		||||
        "//vendor:k8s.io/apiserver/pkg/util/feature",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -217,7 +217,7 @@ func (n *NodeInfo) String() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasPodAffinityConstraints(pod *v1.Pod) bool {
 | 
			
		||||
	affinity := v1.ReconcileAffinity(pod)
 | 
			
		||||
	affinity := ReconcileAffinity(pod)
 | 
			
		||||
	return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								plugin/pkg/scheduler/schedulercache/reconcile_affinity.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								plugin/pkg/scheduler/schedulercache/reconcile_affinity.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2017 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 schedulercache
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/features"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Reconcile api and annotation affinity definitions.
 | 
			
		||||
// When alpha affinity feature is not enabled, always take affinity
 | 
			
		||||
// from PodSpec.When alpha affinity feature is enabled, if affinity
 | 
			
		||||
// is not set in PodSpec, take affinity from annotation.
 | 
			
		||||
// When alpha affinity feature is enabled, if affinity is set in PodSpec,
 | 
			
		||||
// take node affinity, pod affinity, and pod anti-affinity individually
 | 
			
		||||
// using the following rule: take affinity from PodSpec if it is defined,
 | 
			
		||||
// otherwise take from annotation if it is defined.
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func ReconcileAffinity(pod *v1.Pod) *v1.Affinity {
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	if utilfeature.DefaultFeatureGate.Enabled(features.AffinityInAnnotations) {
 | 
			
		||||
		annotationsAffinity, _ := v1.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
		if affinity == nil && annotationsAffinity != nil {
 | 
			
		||||
			affinity = annotationsAffinity
 | 
			
		||||
		} else if annotationsAffinity != nil {
 | 
			
		||||
			if affinity != nil && affinity.NodeAffinity == nil && annotationsAffinity.NodeAffinity != nil {
 | 
			
		||||
				affinity.NodeAffinity = annotationsAffinity.NodeAffinity
 | 
			
		||||
			}
 | 
			
		||||
			if affinity != nil && affinity.PodAffinity == nil && annotationsAffinity.PodAffinity != nil {
 | 
			
		||||
				affinity.PodAffinity = annotationsAffinity.PodAffinity
 | 
			
		||||
			}
 | 
			
		||||
			if affinity != nil && affinity.PodAntiAffinity == nil && annotationsAffinity.PodAntiAffinity != nil {
 | 
			
		||||
				affinity.PodAntiAffinity = annotationsAffinity.PodAntiAffinity
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return affinity
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										151
									
								
								plugin/pkg/scheduler/schedulercache/reconcile_affinity_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								plugin/pkg/scheduler/schedulercache/reconcile_affinity_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2017 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 schedulercache
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
func TestReconcileAffinity(t *testing.T) {
 | 
			
		||||
	baseAffinity := &v1.Affinity{
 | 
			
		||||
		NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
 | 
			
		||||
				NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
					{
 | 
			
		||||
						MatchExpressions: []v1.NodeSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "foo",
 | 
			
		||||
								Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
								Values:   []string{"bar", "value2"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "security",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
								Values:   []string{"securityscan"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "topologyKey1",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "service",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
								Values:   []string{"S1", "value2"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "topologyKey2",
 | 
			
		||||
					Namespaces:  []string{"ns1"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nodeAffinityAnnotation := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"nodeAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [
 | 
			
		||||
			{
 | 
			
		||||
				"weight": 2,
 | 
			
		||||
				"preference": {"matchExpressions": [
 | 
			
		||||
					{
 | 
			
		||||
						"key": "foo",
 | 
			
		||||
						"operator": "In", "values": ["bar"]
 | 
			
		||||
					}
 | 
			
		||||
				]}
 | 
			
		||||
			}
 | 
			
		||||
		]}}`,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		pod                *v1.Pod
 | 
			
		||||
		expected           *v1.Affinity
 | 
			
		||||
		annotationsEnabled bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			// affinity is set in both PodSpec and annotations; take from PodSpec.
 | 
			
		||||
			pod: &v1.Pod{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Annotations: nodeAffinityAnnotation,
 | 
			
		||||
				},
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					Affinity: baseAffinity,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected:           baseAffinity,
 | 
			
		||||
			annotationsEnabled: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// affinity is only set in annotation; take from annotation.
 | 
			
		||||
			pod: &v1.Pod{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Annotations: nodeAffinityAnnotation,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: &v1.Affinity{
 | 
			
		||||
				NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []v1.PreferredSchedulingTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 2,
 | 
			
		||||
							Preference: v1.NodeSelectorTerm{
 | 
			
		||||
								MatchExpressions: []v1.NodeSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "foo",
 | 
			
		||||
										Operator: v1.NodeSelectorOpIn,
 | 
			
		||||
										Values:   []string{"bar"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			annotationsEnabled: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range testCases {
 | 
			
		||||
		utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("AffinityInAnnotations=%t", tc.annotationsEnabled))
 | 
			
		||||
		affinity := ReconcileAffinity(tc.pod)
 | 
			
		||||
		if !reflect.DeepEqual(affinity, tc.expected) {
 | 
			
		||||
			t.Errorf("[%v] Did not get expected affinity:\n\n%v\n\n. got:\n\n %v", i, tc.expected, affinity)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -108,7 +108,10 @@ type FeatureGate interface {
 | 
			
		||||
	// alpha: v1.5
 | 
			
		||||
	ExperimentalHostUserNamespaceDefaulting() bool
 | 
			
		||||
 | 
			
		||||
	AnninityInAnnotations() bool
 | 
			
		||||
	// owner: @davidopp
 | 
			
		||||
	// alpha: v1.6
 | 
			
		||||
	// TODO: remove when alpha support for affinity is removed
 | 
			
		||||
	AffinityInAnnotations() bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// featureGate implements FeatureGate as well as pflag.Value for flag parsing.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user