mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #39478 from rrati/pod-affinity-api-fields
Automatic merge from submit-queue (batch tested with PRs 39803, 39698, 39537, 39478) [scheduling] Moved pod affinity and anti-affinity from annotations to api fields #25319 Converted pod affinity and anti-affinity from annotations to api fields Related: #25319 Related: #34508 **Release note**: ```Pod affinity and anti-affinity has moved from annotations to api fields in the pod spec. Pod affinity or anti-affinity that is defined in the annotations will be ignored.```
This commit is contained in:
		@@ -486,20 +486,6 @@ const (
 | 
			
		||||
	UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetAffinityFromPod gets the json serialized affinity data from Pod.Annotations
 | 
			
		||||
// and converts it to the Affinity type in api.
 | 
			
		||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
 | 
			
		||||
	if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
 | 
			
		||||
		var affinity Affinity
 | 
			
		||||
		err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return &affinity, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
 | 
			
		||||
// and converts it to the []Toleration type in api.
 | 
			
		||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -241,62 +241,6 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetAffinityFromPod(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		pod       *Pod
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pod:       &Pod{},
 | 
			
		||||
			expectErr: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &Pod{
 | 
			
		||||
				ObjectMeta: ObjectMeta{
 | 
			
		||||
					Annotations: map[string]string{
 | 
			
		||||
						AffinityAnnotationKey: `
 | 
			
		||||
						{"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": {
 | 
			
		||||
							"nodeSelectorTerms": [{
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "foo",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							}]
 | 
			
		||||
						}}}`,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectErr: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &Pod{
 | 
			
		||||
				ObjectMeta: ObjectMeta{
 | 
			
		||||
					Annotations: map[string]string{
 | 
			
		||||
						AffinityAnnotationKey: `
 | 
			
		||||
						{"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": {
 | 
			
		||||
							"nodeSelectorTerms": [{
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "foo",
 | 
			
		||||
						`,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tc := range testCases {
 | 
			
		||||
		_, err := GetAffinityFromPodAnnotations(tc.pod.Annotations)
 | 
			
		||||
		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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTaintToString(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		taint          *Taint
 | 
			
		||||
 
 | 
			
		||||
@@ -331,7 +331,6 @@ func TestEncode_Ptr(t *testing.T) {
 | 
			
		||||
			TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
 | 
			
		||||
			SecurityContext: &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	obj := runtime.Object(pod)
 | 
			
		||||
@@ -345,7 +344,6 @@ func TestEncode_Ptr(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	if !api.Semantic.DeepEqual(obj2, pod) {
 | 
			
		||||
		t.Errorf("\nExpected:\n\n %#v,\n\nGot:\n\n %#vDiff: %v\n\n", pod, obj2, diff.ObjectDiff(obj2, pod))
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ func DeepEqualSafePodSpec() api.PodSpec {
 | 
			
		||||
		DNSPolicy:                     api.DNSClusterFirst,
 | 
			
		||||
		TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
		SecurityContext:               &api.PodSecurityContext{},
 | 
			
		||||
		Affinity:                      &api.Affinity{},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -174,9 +174,6 @@ func SetDefaults_PodSpec(obj *PodSpec) {
 | 
			
		||||
		period := int64(DefaultTerminationGracePeriodSeconds)
 | 
			
		||||
		obj.TerminationGracePeriodSeconds = &period
 | 
			
		||||
	}
 | 
			
		||||
	if obj.Affinity == nil {
 | 
			
		||||
		obj.Affinity = &Affinity{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func SetDefaults_Probe(obj *Probe) {
 | 
			
		||||
	if obj.TimeoutSeconds == 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -101,10 +101,6 @@ func ValidateDNS1123Subdomain(value string, fldPath *field.Path) field.ErrorList
 | 
			
		||||
 | 
			
		||||
func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.PodSpec, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
	allErrs := field.ErrorList{}
 | 
			
		||||
	if annotations[api.AffinityAnnotationKey] != "" {
 | 
			
		||||
		allErrs = append(allErrs, ValidateAffinityInPodAnnotations(annotations, fldPath)...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if annotations[api.TolerationsAnnotationKey] != "" {
 | 
			
		||||
		allErrs = append(allErrs, ValidateTolerationsInPodAnnotations(annotations, fldPath)...)
 | 
			
		||||
	}
 | 
			
		||||
@@ -1672,7 +1668,14 @@ func validateAffinity(affinity *api.Affinity, fldPath *field.Path) field.ErrorLi
 | 
			
		||||
				allErrs = append(allErrs, ValidatePreferredSchedulingTerms(na.PreferredDuringSchedulingIgnoredDuringExecution, fldPath.Child("preferredDuringSchedulingIgnoredDuringExecution"))...)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if affinity.PodAffinity != nil {
 | 
			
		||||
			allErrs = append(allErrs, validatePodAffinity(affinity.PodAffinity, fldPath.Child("podAffinity"))...)
 | 
			
		||||
		}
 | 
			
		||||
		if affinity.PodAntiAffinity != nil {
 | 
			
		||||
			allErrs = append(allErrs, validatePodAntiAffinity(affinity.PodAntiAffinity, fldPath.Child("podAntiAffinity"))...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return allErrs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1968,30 +1971,6 @@ func validatePodAffinity(podAffinity *api.PodAffinity, fldPath *field.Path) fiel
 | 
			
		||||
	return allErrs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateAffinityInPodAnnotations tests that the serialized Affinity in Pod.Annotations has valid data
 | 
			
		||||
func ValidateAffinityInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
	allErrs := field.ErrorList{}
 | 
			
		||||
 | 
			
		||||
	affinity, err := api.GetAffinityFromPodAnnotations(annotations)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		allErrs = append(allErrs, field.Invalid(fldPath, api.AffinityAnnotationKey, err.Error()))
 | 
			
		||||
		return allErrs
 | 
			
		||||
	}
 | 
			
		||||
	if affinity == nil {
 | 
			
		||||
		return allErrs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	affinityFldPath := fldPath.Child(api.AffinityAnnotationKey)
 | 
			
		||||
	if affinity.PodAffinity != nil {
 | 
			
		||||
		allErrs = append(allErrs, validatePodAffinity(affinity.PodAffinity, affinityFldPath.Child("podAffinity"))...)
 | 
			
		||||
	}
 | 
			
		||||
	if affinity.PodAntiAffinity != nil {
 | 
			
		||||
		allErrs = append(allErrs, validatePodAntiAffinity(affinity.PodAntiAffinity, affinityFldPath.Child("podAntiAffinity"))...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return allErrs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateTolerationsInPodAnnotations tests that the serialized tolerations in Pod.Annotations has valid data
 | 
			
		||||
func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
 | 
			
		||||
	allErrs := field.ErrorList{}
 | 
			
		||||
 
 | 
			
		||||
@@ -3076,11 +3076,18 @@ func TestValidatePodSpec(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestValidatePod(t *testing.T) {
 | 
			
		||||
	validPodSpec := api.PodSpec{
 | 
			
		||||
	validPodSpec := func(affinity *api.Affinity) api.PodSpec {
 | 
			
		||||
		spec := api.PodSpec{
 | 
			
		||||
			Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
			RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
			DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
		}
 | 
			
		||||
		if affinity != nil {
 | 
			
		||||
			spec.Affinity = affinity
 | 
			
		||||
		}
 | 
			
		||||
		return spec
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	successCases := []api.Pod{
 | 
			
		||||
		{ // Basic fields.
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
 | 
			
		||||
@@ -3111,10 +3118,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
			},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
				RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
				DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
			Spec: validPodSpec(
 | 
			
		||||
				// TODO: Uncomment and move this block and move inside NodeAffinity once
 | 
			
		||||
				// RequiredDuringSchedulingRequiredDuringExecution is implemented
 | 
			
		||||
				//		RequiredDuringSchedulingRequiredDuringExecution: &api.NodeSelector{
 | 
			
		||||
@@ -3129,7 +3133,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
				//				},
 | 
			
		||||
				//			},
 | 
			
		||||
				//		},
 | 
			
		||||
				Affinity: &api.Affinity{
 | 
			
		||||
				&api.Affinity{
 | 
			
		||||
					NodeAffinity: &api.NodeAffinity{
 | 
			
		||||
						RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
			
		||||
							NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
			
		||||
@@ -3160,7 +3164,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			),
 | 
			
		||||
		},
 | 
			
		||||
		{ // Serialized pod affinity in affinity requirements in annotations.
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3179,38 +3183,44 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
				//			"namespaces":["ns"],
 | 
			
		||||
				//			"topologyKey": "zone"
 | 
			
		||||
				//		}]
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
			},
 | 
			
		||||
							"topologyKey": "zone",
 | 
			
		||||
							"namespaces": ["ns"]
 | 
			
		||||
						}],
 | 
			
		||||
						"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"weight": 10,
 | 
			
		||||
							"podAffinityTerm": {
 | 
			
		||||
								"labelSelector": {
 | 
			
		||||
									"matchExpressions": [{
 | 
			
		||||
										"key": "key2",
 | 
			
		||||
										"operator": "NotIn",
 | 
			
		||||
										"values": ["value1", "value2"]
 | 
			
		||||
									}]
 | 
			
		||||
								},
 | 
			
		||||
								"namespaces": ["ns"],
 | 
			
		||||
								"topologyKey": "region"
 | 
			
		||||
							}
 | 
			
		||||
						 }]
 | 
			
		||||
					}}`,
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAffinity: &api.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "key2",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"value1", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: "zone",
 | 
			
		||||
							Namespaces:  []string{"ns"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 10,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpNotIn,
 | 
			
		||||
											Values:   []string{"value1", "value2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces:  []string{"ns"},
 | 
			
		||||
								TopologyKey: "region",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		{ // Serialized pod anti affinity with different Label Operators in affinity requirements in annotations.
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3229,36 +3239,42 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
				//			"namespaces":["ns"],
 | 
			
		||||
				//			"topologyKey": "zone"
 | 
			
		||||
				//		}]
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "Exists"
 | 
			
		||||
								}]
 | 
			
		||||
			},
 | 
			
		||||
							"topologyKey": "zone",
 | 
			
		||||
							"namespaces": ["ns"]
 | 
			
		||||
						}],
 | 
			
		||||
						"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"weight": 10,
 | 
			
		||||
							"podAffinityTerm": {
 | 
			
		||||
								"labelSelector": {
 | 
			
		||||
									"matchExpressions": [{
 | 
			
		||||
										"key": "key2",
 | 
			
		||||
										"operator": "DoesNotExist"
 | 
			
		||||
									}]
 | 
			
		||||
								},
 | 
			
		||||
								"namespaces": ["ns"],
 | 
			
		||||
								"topologyKey": "region"
 | 
			
		||||
							}
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "key2",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: "zone",
 | 
			
		||||
							Namespaces:  []string{"ns"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 10,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces:  []string{"ns"},
 | 
			
		||||
								TopologyKey: "region",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		{ // populate tolerations equal operator in annotations.
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3274,7 +3290,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // populate tolerations exists operator in annotations.
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3289,7 +3305,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // empty operator is ok for toleration
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3304,7 +3320,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // empty efffect is ok for toleration
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3319,7 +3335,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // docker default seccomp profile
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3329,7 +3345,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "docker/default",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // unconfined seccomp profile
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3339,7 +3355,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "unconfined",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // localhost seccomp profile
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3349,7 +3365,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "localhost/foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // localhost seccomp profile for a container
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3359,7 +3375,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompContainerAnnotationKeyPrefix + "foo": "localhost/foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // default AppArmor profile for a container
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3369,7 +3385,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					apparmor.ContainerAnnotationKeyPrefix + "ctr": apparmor.ProfileRuntimeDefault,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // default AppArmor profile for an init container
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3394,7 +3410,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					apparmor.ContainerAnnotationKeyPrefix + "ctr": apparmor.ProfileNamePrefix + "foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // syntactically valid sysctls
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3405,7 +3421,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.UnsafeSysctlsPodAnnotationKey: "knet.ipv4.route.min_pmtu=1000",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		{ // valid opaque integer resources for init container
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "valid-opaque-int", Namespace: "ns"},
 | 
			
		||||
@@ -3502,11 +3518,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
			},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
				RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
				DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
				Affinity: &api.Affinity{
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				NodeAffinity: &api.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
			
		||||
@@ -3521,19 +3533,14 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid preferredSchedulingTerm in node affinity, weight should be in range 1-100": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
			},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
				RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
				DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
				Affinity: &api.Affinity{
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				NodeAffinity: &api.NodeAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.PreferredSchedulingTerm{
 | 
			
		||||
						{
 | 
			
		||||
@@ -3550,37 +3557,27 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid requiredDuringSchedulingIgnoredDuringExecution node selector, nodeSelectorTerms must have at least one term": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
			},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
				RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
				DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
				Affinity: &api.Affinity{
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				NodeAffinity: &api.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []api.NodeSelectorTerm{},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid requiredDuringSchedulingIgnoredDuringExecution node selector term, matchExpressions must have at least one node selector requirement": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
			},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers:    []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
 | 
			
		||||
				RestartPolicy: api.RestartPolicyAlways,
 | 
			
		||||
				DNSPolicy:     api.DNSClusterFirst,
 | 
			
		||||
				Affinity: &api.Affinity{
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				NodeAffinity: &api.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
			
		||||
@@ -3590,183 +3587,165 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid weight in preferredDuringSchedulingIgnoredDuringExecution in pod affinity annotations, weight should be in range 1-100": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 109,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAffinity: &api.PodAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "NotIn",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": "region"
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
							Weight: 109,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpNotIn,
 | 
			
		||||
											Values:   []string{"value1", "value2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces:  []string{"ns"},
 | 
			
		||||
								TopologyKey: "region",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid labelSelector in preferredDuringSchedulingIgnoredDuringExecution in podaffinity annotations, values should be empty if the operator is Exists": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "Exists",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": "region"
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
							Weight: 10,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
											Values:   []string{"value1", "value2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces:  []string{"ns"},
 | 
			
		||||
								TopologyKey: "region",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid name space in preferredDuringSchedulingIgnoredDuringExecution in podaffinity annotations, name space shouldbe valid": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAffinity: &api.PodAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "Exists",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["INVALID_NAMESPACE"],
 | 
			
		||||
							"topologyKey": "region"
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
		},
 | 
			
		||||
		"invalid labelOperator in preferredDuringSchedulingIgnoredDuringExecution in podantiaffinity annotations, labelOperator should be proper": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
							Weight: 10,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "WrongOp",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": "region"
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces:  []string{"INVALID_NAMESPACE"},
 | 
			
		||||
								TopologyKey: "region",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid pod affinity, empty topologyKey is not allowed for hard pod affinity": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAffinity: &api.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": ""
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "key2",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"value1", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
							},
 | 
			
		||||
							Namespaces: []string{"ns"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid pod anti-affinity, empty topologyKey is not allowed for hard pod anti-affinity": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": ""
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "key2",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"value1", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
							},
 | 
			
		||||
							Namespaces: []string{"ns"},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid pod anti-affinity, empty topologyKey is not allowed for soft pod affinity": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
				Name:      "123",
 | 
			
		||||
				Namespace: "ns",
 | 
			
		||||
				Annotations: map[string]string{
 | 
			
		||||
					api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 10,
 | 
			
		||||
						"podAffinityTerm":
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec(&api.Affinity{
 | 
			
		||||
				PodAffinity: &api.PodAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "key2",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values": ["value1", "value2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces": ["ns"],
 | 
			
		||||
							"topologyKey": ""
 | 
			
		||||
						}
 | 
			
		||||
					}]}}`,
 | 
			
		||||
							Weight: 10,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "key2",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpNotIn,
 | 
			
		||||
											Values:   []string{"value1", "value2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
								},
 | 
			
		||||
								Namespaces: []string{"ns"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid toleration key": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3782,7 +3761,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid toleration operator": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3798,7 +3777,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"value must be empty when `operator` is 'Exists'": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3814,7 +3793,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					}]`,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must be a valid pod seccomp profile": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3824,7 +3803,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must be a valid container seccomp profile": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3834,7 +3813,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompContainerAnnotationKeyPrefix + "foo": "foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must be a non-empty container name in seccomp annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3844,7 +3823,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompContainerAnnotationKeyPrefix: "foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must be a non-empty container profile in seccomp annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3854,7 +3833,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompContainerAnnotationKeyPrefix + "foo": "",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must be a relative path in a node-local seccomp profile annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3864,7 +3843,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "localhost//foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"must not start with '../'": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3874,7 +3853,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SeccompPodAnnotationKey: "localhost/../foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"AppArmor profile must apply to a container": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3901,7 +3880,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					apparmor.ContainerAnnotationKeyPrefix + "ctr": "bad-name",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"only default AppArmor profile may start with runtime/": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3911,7 +3890,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					apparmor.ContainerAnnotationKeyPrefix + "ctr": "runtime/foo",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid sysctl annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3921,7 +3900,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SysctlsPodAnnotationKey: "foo:",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid comma-separated sysctl annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3931,7 +3910,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SysctlsPodAnnotationKey: "kernel.msgmax,",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid unsafe sysctl annotation": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3941,7 +3920,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.SysctlsPodAnnotationKey: "foo:",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"intersecting safe sysctls and unsafe sysctls annotations": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{
 | 
			
		||||
@@ -3952,7 +3931,7 @@ func TestValidatePod(t *testing.T) {
 | 
			
		||||
					api.UnsafeSysctlsPodAnnotationKey: "kernel.shmmax=10000000",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Spec: validPodSpec,
 | 
			
		||||
			Spec: validPodSpec(nil),
 | 
			
		||||
		},
 | 
			
		||||
		"invalid opaque integer resource requirement: request must be <= limit": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,6 @@ func TestSetDefaultDaemonSet(t *testing.T) {
 | 
			
		||||
			RestartPolicy:                 v1.RestartPolicyAlways,
 | 
			
		||||
			SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
			TerminationGracePeriodSeconds: &period,
 | 
			
		||||
			Affinity:                      &v1.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
		ObjectMeta: v1.ObjectMeta{
 | 
			
		||||
			Labels: defaultLabels,
 | 
			
		||||
@@ -52,7 +51,6 @@ func TestSetDefaultDaemonSet(t *testing.T) {
 | 
			
		||||
			RestartPolicy:                 v1.RestartPolicyAlways,
 | 
			
		||||
			SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
			TerminationGracePeriodSeconds: &period,
 | 
			
		||||
			Affinity:                      &v1.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
@@ -157,7 +155,6 @@ func TestSetDefaultDeployment(t *testing.T) {
 | 
			
		||||
			RestartPolicy:                 v1.RestartPolicyAlways,
 | 
			
		||||
			SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
			TerminationGracePeriodSeconds: &period,
 | 
			
		||||
			Affinity:                      &v1.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -132,7 +132,6 @@ func TestMerge(t *testing.T) {
 | 
			
		||||
					DNSPolicy:                     api.DNSClusterFirst,
 | 
			
		||||
					TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
					SecurityContext:               &api.PodSecurityContext{},
 | 
			
		||||
					Affinity:                      &api.Affinity{},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,6 @@ func TestDecodeSinglePod(t *testing.T) {
 | 
			
		||||
				SecurityContext:        securitycontext.ValidSecurityContextWithContainerDefaults(),
 | 
			
		||||
			}},
 | 
			
		||||
			SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &v1.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	json, err := runtime.Encode(testapi.Default.Codec(), pod)
 | 
			
		||||
@@ -115,7 +114,6 @@ func TestDecodePodList(t *testing.T) {
 | 
			
		||||
				SecurityContext:        securitycontext.ValidSecurityContextWithContainerDefaults(),
 | 
			
		||||
			}},
 | 
			
		||||
			SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &v1.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	podList := &v1.PodList{
 | 
			
		||||
 
 | 
			
		||||
@@ -188,7 +188,6 @@ func getTestCases(hostname types.NodeName) []*testCase {
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					Containers:      []v1.Container{{Name: "image", Image: "test/image", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
 | 
			
		||||
					SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
					Affinity:        &v1.Affinity{},
 | 
			
		||||
				},
 | 
			
		||||
				Status: v1.PodStatus{
 | 
			
		||||
					Phase: v1.PodPending,
 | 
			
		||||
@@ -214,7 +213,6 @@ func getTestCases(hostname types.NodeName) []*testCase {
 | 
			
		||||
						ImagePullPolicy:        "Always",
 | 
			
		||||
						SecurityContext:        securitycontext.ValidSecurityContextWithContainerDefaults()}},
 | 
			
		||||
					SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
					Affinity:        &v1.Affinity{},
 | 
			
		||||
				},
 | 
			
		||||
				Status: v1.PodStatus{
 | 
			
		||||
					Phase: v1.PodPending,
 | 
			
		||||
 
 | 
			
		||||
@@ -148,7 +148,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
					NodeName:        string(nodeName),
 | 
			
		||||
					Containers:      []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}},
 | 
			
		||||
					SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
					Affinity:        &v1.Affinity{},
 | 
			
		||||
				},
 | 
			
		||||
				Status: v1.PodStatus{
 | 
			
		||||
					Phase: v1.PodPending,
 | 
			
		||||
@@ -170,7 +169,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
						DNSPolicy:                     v1.DNSClusterFirst,
 | 
			
		||||
						SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
						TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
						Affinity:                      &v1.Affinity{},
 | 
			
		||||
 | 
			
		||||
						Containers: []v1.Container{{
 | 
			
		||||
							Name:  "1",
 | 
			
		||||
@@ -201,7 +199,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
							NodeName:        nodeName,
 | 
			
		||||
							Containers:      []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}},
 | 
			
		||||
							SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
							Affinity:        &v1.Affinity{},
 | 
			
		||||
						},
 | 
			
		||||
						Status: v1.PodStatus{
 | 
			
		||||
							Phase: v1.PodPending,
 | 
			
		||||
@@ -216,7 +213,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
							NodeName:        nodeName,
 | 
			
		||||
							Containers:      []v1.Container{{Name: "2", Image: "bar:bartag", ImagePullPolicy: ""}},
 | 
			
		||||
							SecurityContext: &v1.PodSecurityContext{},
 | 
			
		||||
							Affinity:        &v1.Affinity{},
 | 
			
		||||
						},
 | 
			
		||||
						Status: v1.PodStatus{
 | 
			
		||||
							Phase: v1.PodPending,
 | 
			
		||||
@@ -240,7 +236,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
						DNSPolicy:                     v1.DNSClusterFirst,
 | 
			
		||||
						TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
						SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
						Affinity:                      &v1.Affinity{},
 | 
			
		||||
 | 
			
		||||
						Containers: []v1.Container{{
 | 
			
		||||
							Name:  "1",
 | 
			
		||||
@@ -267,7 +262,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
 | 
			
		||||
						DNSPolicy:                     v1.DNSClusterFirst,
 | 
			
		||||
						TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
						SecurityContext:               &v1.PodSecurityContext{},
 | 
			
		||||
						Affinity:                      &v1.Affinity{},
 | 
			
		||||
 | 
			
		||||
						Containers: []v1.Container{{
 | 
			
		||||
							Name:  "2",
 | 
			
		||||
 
 | 
			
		||||
@@ -484,7 +484,8 @@ func TestCriticalPrioritySorting(t *testing.T) {
 | 
			
		||||
			Requests: v1.ResourceList{
 | 
			
		||||
				"memory": resource.MustParse("90"),
 | 
			
		||||
			},
 | 
			
		||||
		}}}}
 | 
			
		||||
		}}},
 | 
			
		||||
	}
 | 
			
		||||
	pods := []*v1.Pod{
 | 
			
		||||
		podWithUidNameNsSpec("000000000", "newpod", "foo", spec),
 | 
			
		||||
		podWithUidNameNsSpec("987654321", "oldpod", "foo", spec),
 | 
			
		||||
@@ -637,7 +638,8 @@ func TestHandleMemExceeded(t *testing.T) {
 | 
			
		||||
			Requests: v1.ResourceList{
 | 
			
		||||
				"memory": resource.MustParse("90"),
 | 
			
		||||
			},
 | 
			
		||||
		}}}}
 | 
			
		||||
		}}},
 | 
			
		||||
	}
 | 
			
		||||
	pods := []*v1.Pod{
 | 
			
		||||
		podWithUidNameNsSpec("123456789", "newpod", "foo", spec),
 | 
			
		||||
		podWithUidNameNsSpec("987654321", "oldpod", "foo", spec),
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,6 @@ func validNewPod() *api.Pod {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			SecurityContext: &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -660,7 +659,6 @@ func TestEtcdUpdateScheduled(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			SecurityContext: &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}, nil, 1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -689,7 +687,6 @@ func TestEtcdUpdateScheduled(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
			TerminationGracePeriodSeconds: &grace,
 | 
			
		||||
			SecurityContext:               &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:                      &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	_, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme))
 | 
			
		||||
@@ -730,7 +727,6 @@ func TestEtcdUpdateStatus(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			SecurityContext: &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	err := storage.Storage.Create(ctx, key, &podStart, nil, 0)
 | 
			
		||||
@@ -755,7 +751,6 @@ func TestEtcdUpdateStatus(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			SecurityContext: &api.PodSecurityContext{},
 | 
			
		||||
			Affinity:        &api.Affinity{},
 | 
			
		||||
		},
 | 
			
		||||
		Status: api.PodStatus{
 | 
			
		||||
			Phase:   api.PodRunning,
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ go_library(
 | 
			
		||||
        "//pkg/admission:go_default_library",
 | 
			
		||||
        "//pkg/api:go_default_library",
 | 
			
		||||
        "//pkg/api/errors:go_default_library",
 | 
			
		||||
        "//vendor:github.com/golang/glog",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/glog"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/admission"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
@@ -56,11 +55,7 @@ func (p *plugin) Admit(attributes admission.Attributes) (err error) {
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return apierrors.NewBadRequest("Resource was marked with kind Pod but was unable to be converted")
 | 
			
		||||
	}
 | 
			
		||||
	affinity, err := api.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		glog.V(5).Infof("Invalid Affinity detected, but we will leave handling of this to validation phase")
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	if affinity != nil && affinity.PodAntiAffinity != nil {
 | 
			
		||||
		var podAntiAffinityTerms []api.PodAffinityTerm
 | 
			
		||||
		if len(affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,109 +32,120 @@ func TestInterPodAffinityAdmission(t *testing.T) {
 | 
			
		||||
		Spec: api.PodSpec{},
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		affinity      map[string]string
 | 
			
		||||
		affinity      *api.Affinity
 | 
			
		||||
		errorExpected bool
 | 
			
		||||
	}{
 | 
			
		||||
		// empty affinity its success.
 | 
			
		||||
		{
 | 
			
		||||
			affinity:      map[string]string{},
 | 
			
		||||
			affinity:      &api.Affinity{},
 | 
			
		||||
			errorExpected: false,
 | 
			
		||||
		},
 | 
			
		||||
		// what ever topologyKey in preferredDuringSchedulingIgnoredDuringExecution, the admission should success.
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"weight": 5,
 | 
			
		||||
							"podAffinityTerm": {
 | 
			
		||||
								"labelSelector": {
 | 
			
		||||
									"matchExpressions": [{
 | 
			
		||||
										"key": "security",
 | 
			
		||||
										"operator": "In",
 | 
			
		||||
										"values":["S2"]
 | 
			
		||||
										}]
 | 
			
		||||
			affinity: &api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 5,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "security",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
											Values:   []string{"S2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								TopologyKey: "az",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
								"namespaces": [],
 | 
			
		||||
								"topologyKey": "az"
 | 
			
		||||
							}
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			errorExpected: false,
 | 
			
		||||
		},
 | 
			
		||||
		// valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution,
 | 
			
		||||
		// plus any topologyKey in preferredDuringSchedulingIgnoredDuringExecution, then admission success.
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"weight": 5,
 | 
			
		||||
							"podAffinityTerm": {
 | 
			
		||||
								"labelSelector": {
 | 
			
		||||
									"matchExpressions": [{
 | 
			
		||||
										"key": "security",
 | 
			
		||||
										"operator": "In",
 | 
			
		||||
										"values":["S2"]
 | 
			
		||||
									}]
 | 
			
		||||
			affinity: &api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							Weight: 5,
 | 
			
		||||
							PodAffinityTerm: api.PodAffinityTerm{
 | 
			
		||||
								LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
									MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
										{
 | 
			
		||||
											Key:      "security",
 | 
			
		||||
											Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
											Values:   []string{"S2"},
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
								TopologyKey: "az",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: metav1.LabelHostname,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
								"namespaces": [],
 | 
			
		||||
								"topologyKey": "az"
 | 
			
		||||
							}
 | 
			
		||||
						}],
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
				},
 | 
			
		||||
							"namespaces": [],
 | 
			
		||||
							"topologyKey": "` + metav1.LabelHostname + `"
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			errorExpected: false,
 | 
			
		||||
		},
 | 
			
		||||
		// valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission success.
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
			affinity: &api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: metav1.LabelHostname,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
							"namespaces":[],
 | 
			
		||||
							"topologyKey": "` + metav1.LabelHostname + `"
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			errorExpected: false,
 | 
			
		||||
		},
 | 
			
		||||
		// invalid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission fails.
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
			affinity: &api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: " zone ",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
							"namespaces":[],
 | 
			
		||||
							"topologyKey": " zone "
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			errorExpected: true,
 | 
			
		||||
		},
 | 
			
		||||
@@ -161,59 +172,51 @@ func TestInterPodAffinityAdmission(t *testing.T) {
 | 
			
		||||
		//  }
 | 
			
		||||
		// list of requiredDuringSchedulingIgnoredDuringExecution middle element topologyKey is not valid.
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces":[],
 | 
			
		||||
							"topologyKey": "` + metav1.LabelHostname + `"
 | 
			
		||||
						},
 | 
			
		||||
			affinity: &api.Affinity{
 | 
			
		||||
				PodAntiAffinity: &api.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
							},
 | 
			
		||||
							"namespaces":[],
 | 
			
		||||
							"topologyKey": " zone "
 | 
			
		||||
						},
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "security",
 | 
			
		||||
									"operator": "In",
 | 
			
		||||
									"values":["S2"]
 | 
			
		||||
								}]
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: metav1.LabelHostname,
 | 
			
		||||
						}, {
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: " zone ",
 | 
			
		||||
						}, {
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: metav1.LabelHostname,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
							"namespaces": [],
 | 
			
		||||
							"topologyKey": "` + metav1.LabelHostname + `"
 | 
			
		||||
						}]
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			errorExpected: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			affinity: map[string]string{
 | 
			
		||||
				api.AffinityAnnotationKey: `
 | 
			
		||||
					{"podAntiAffinity": {
 | 
			
		||||
						"thisIsAInvalidAffinity": [{}
 | 
			
		||||
					}}`,
 | 
			
		||||
			},
 | 
			
		||||
			// however, we should not get error here
 | 
			
		||||
			errorExpected: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		pod.ObjectMeta.Annotations = test.affinity
 | 
			
		||||
		pod.Spec.Affinity = test.affinity
 | 
			
		||||
		err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
 | 
			
		||||
 | 
			
		||||
		if test.errorExpected && err == nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ go_test(
 | 
			
		||||
        "//plugin/pkg/scheduler/algorithm:go_default_library",
 | 
			
		||||
        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
			
		||||
        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
			
		||||
        "//vendor:k8s.io/apimachinery/pkg/labels",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -904,10 +904,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta interface
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now check if <pod> requirements will be satisfied on this node.
 | 
			
		||||
	affinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) {
 | 
			
		||||
		return true, nil, nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -1008,11 +1005,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler
 | 
			
		||||
		}
 | 
			
		||||
		var nodeResult []matchingPodAntiAffinityTerm
 | 
			
		||||
		for _, existingPod := range nodeInfo.PodsWithAffinity() {
 | 
			
		||||
			affinity, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				catchError(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			affinity := existingPod.Spec.Affinity
 | 
			
		||||
			if affinity == nil {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
@@ -1040,10 +1033,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, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		affinity := pod.Spec.Affinity
 | 
			
		||||
		if affinity != nil && affinity.PodAntiAffinity != nil {
 | 
			
		||||
			existingPodNode, err := c.info.GetNodeInfo(existingPod.Spec.NodeName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -118,10 +118,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, err := v1.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil
 | 
			
		||||
	hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil
 | 
			
		||||
 | 
			
		||||
@@ -142,10 +139,7 @@ func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, node
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		existingPodAffinity, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		existingPodAffinity := existingPod.Spec.Affinity
 | 
			
		||||
		existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil
 | 
			
		||||
		existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,188 +65,203 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		"security": "S2",
 | 
			
		||||
	}
 | 
			
		||||
	// considered only preferredDuringSchedulingIgnoredDuringExecution in pod affinity
 | 
			
		||||
	stayWithS1InRegion := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 5,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S1"]
 | 
			
		||||
						}]
 | 
			
		||||
					},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	stayWithS2InRegion := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 6,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S2"]
 | 
			
		||||
						}]
 | 
			
		||||
					},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	affinity3 := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [
 | 
			
		||||
	stayWithS1InRegion := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					"weight": 8,
 | 
			
		||||
					"podAffinityTerm": {
 | 
			
		||||
						"labelSelector": {
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "NotIn",
 | 
			
		||||
								"values":["S1"]
 | 
			
		||||
							}, {
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "In",
 | 
			
		||||
								"values":["S2"]
 | 
			
		||||
							}]
 | 
			
		||||
						},
 | 
			
		||||
						"namespaces": [],
 | 
			
		||||
						"topologyKey": "region"
 | 
			
		||||
					}
 | 
			
		||||
				}, {
 | 
			
		||||
					"weight": 2,
 | 
			
		||||
					"podAffinityTerm": {
 | 
			
		||||
						"labelSelector": {
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "Exists"
 | 
			
		||||
							}, {
 | 
			
		||||
								"key": "wrongkey",
 | 
			
		||||
								"operator": "DoesNotExist"
 | 
			
		||||
							}]
 | 
			
		||||
						},
 | 
			
		||||
						"namespaces": [],
 | 
			
		||||
						"topologyKey": "region"
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	hardAffinity := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"requiredDuringSchedulingIgnoredDuringExecution": [
 | 
			
		||||
					Weight: 5,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
					"labelSelector":{
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values": ["S1", "value2"]
 | 
			
		||||
						}]
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "region",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	stayWithS2InRegion := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 6,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S2"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "region",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	affinity3 := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 8,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpNotIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								}, {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "Exists"
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S2"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "region",
 | 
			
		||||
					},
 | 
			
		||||
				}, {
 | 
			
		||||
							"key": "wrongkey",
 | 
			
		||||
							"operator": "DoesNotExist"
 | 
			
		||||
						}]
 | 
			
		||||
					Weight: 2,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
								}, {
 | 
			
		||||
									Key:      "wrongkey",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "region",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	awayFromS1InAz := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAntiAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 5,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S1"]
 | 
			
		||||
						}]
 | 
			
		||||
		},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "az"
 | 
			
		||||
	}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	hardAffinity := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "security",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
								Values:   []string{"S1", "value2"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "region",
 | 
			
		||||
				}, {
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "security",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
							}, {
 | 
			
		||||
								Key:      "wrongkey",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "region",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	awayFromS1InAz := &v1.Affinity{
 | 
			
		||||
		PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 5,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "az",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	// to stay away from security S2 in any az.
 | 
			
		||||
	awayFromS2InAz := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAntiAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 5,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S2"]
 | 
			
		||||
						}]
 | 
			
		||||
	awayFromS2InAz := &v1.Affinity{
 | 
			
		||||
		PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 5,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S2"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "az",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "az"
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	// to stay with security S1 in same region, stay away from security S2 in any az.
 | 
			
		||||
	stayWithS1InRegionAwayFromS2InAz := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 8,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S1"]
 | 
			
		||||
						}]
 | 
			
		||||
	stayWithS1InRegionAwayFromS2InAz := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 8,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "region",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 5,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S2"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "az",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
			},
 | 
			
		||||
		"podAntiAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 5,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S2"]
 | 
			
		||||
						}]
 | 
			
		||||
		},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "az"
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
@@ -257,7 +272,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		test         string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: map[string]string{}}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}},
 | 
			
		||||
@@ -270,7 +285,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// the node(machine3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score
 | 
			
		||||
		// the node(machine2) that have the label {"region": "China"} (match the topology key) but that have existing pods that mismatch the labelSelector get low score
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS1InRegion}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
@@ -290,7 +305,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// the node3(machine3) that have the label {"region": "India"}, match the topology key but have a different label value, don't have existing pods that match the labelSelector,
 | 
			
		||||
		// get a low score.
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Annotations: stayWithS1InRegion}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			},
 | 
			
		||||
@@ -307,7 +322,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// Then, nodes in regionChina get higher score than nodes in regionIndia, and all the nodes in regionChina should get a same score(high score),
 | 
			
		||||
		// while all the nodes in regionIndia should get another same score(low score).
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS2InRegion}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS2InRegion}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
@@ -328,7 +343,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		// Test with the different operators and values for pod affinity scheduling preference, including some match failures.
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: affinity3}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: affinity3}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
@@ -347,8 +362,8 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS1InRegion}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2, Annotations: stayWithS2InRegion}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1", Affinity: stayWithS1InRegion}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2", Affinity: stayWithS2InRegion}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
@@ -361,8 +376,8 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: hardAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2, Annotations: hardAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardAffinity}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardAffinity}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
@@ -380,7 +395,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// there are 2 nodes, say node1 and node2, both nodes have pods that match the labelSelector and have topology-key in node.Labels.
 | 
			
		||||
		// But there are more pods on node1 that match the preference than node2. Then, node1 get a lower score than node2.
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: awayFromS1InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
@@ -393,7 +408,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
			test:         "Anti Affinity: pod that doesnot match existing pods in node will get high score ",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: awayFromS1InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
@@ -406,7 +421,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
			test:         "Anti Affinity: pod that does not matches topology key & matches the pods in nodes will get higher score comparing to others ",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: awayFromS1InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
@@ -423,8 +438,8 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: awayFromS2InAz}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2, Annotations: awayFromS1InAz}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1", Affinity: awayFromS2InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2", Affinity: awayFromS1InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelAzAz1}},
 | 
			
		||||
@@ -435,7 +450,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		// Test both  affinity and anti-affinity
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS1InRegionAwayFromS2InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
@@ -452,7 +467,7 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// so that all the pods of a RC/service can stay in a same region but trying to separate with each other
 | 
			
		||||
		// machine-1,machine-3,machine-4 are in ChinaRegion others machin-2,machine-5 are in IndiaRegion
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS1InRegionAwayFromS2InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
@@ -478,12 +493,12 @@ func TestInterPodAffinityPriority(t *testing.T) {
 | 
			
		||||
		// for Affinity symmetry, the weights are:       0,  0,  8,  0
 | 
			
		||||
		// for Anti Affinity symmetry, the weights are:  0,  0,  0, -5
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1, Annotations: stayWithS1InRegionAwayFromS2InAz}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabelSecurityS2}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: v1.ObjectMeta{Annotations: stayWithS1InRegionAwayFromS2InAz}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine4"}, ObjectMeta: v1.ObjectMeta{Annotations: awayFromS1InAz}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine3", Affinity: stayWithS1InRegionAwayFromS2InAz}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine4", Affinity: awayFromS1InAz}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
@@ -527,23 +542,23 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) {
 | 
			
		||||
	labelAzAz1 := map[string]string{
 | 
			
		||||
		"az": "az1",
 | 
			
		||||
	}
 | 
			
		||||
	hardPodAffinity := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAffinity": {
 | 
			
		||||
			"requiredDuringSchedulingIgnoredDuringExecution": [
 | 
			
		||||
	hardPodAffinity := &v1.Affinity{
 | 
			
		||||
		PodAffinity: &v1.PodAffinity{
 | 
			
		||||
			RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					"labelSelector":{
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "service",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values": ["S1"]
 | 
			
		||||
						}]
 | 
			
		||||
					LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
						MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
							{
 | 
			
		||||
								Key:      "service",
 | 
			
		||||
								Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
								Values:   []string{"S1"},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					TopologyKey: "region",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": "region"
 | 
			
		||||
				}
 | 
			
		||||
			]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		pod                   *v1.Pod
 | 
			
		||||
@@ -556,8 +571,8 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelServiceS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Annotations: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Annotations: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
@@ -571,8 +586,8 @@ func TestHardPodAffinitySymmetricWeight(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabelServiceS1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Annotations: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Annotations: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}},
 | 
			
		||||
			},
 | 
			
		||||
			nodes: []*v1.Node{
 | 
			
		||||
				{ObjectMeta: v1.ObjectMeta{Name: "machine1", Labels: labelRgChina}},
 | 
			
		||||
@@ -612,24 +627,26 @@ func TestSoftPodAntiAffinityWithFailureDomains(t *testing.T) {
 | 
			
		||||
	podLabel1 := map[string]string{
 | 
			
		||||
		"security": "S1",
 | 
			
		||||
	}
 | 
			
		||||
	antiAffinity1 := map[string]string{
 | 
			
		||||
		v1.AffinityAnnotationKey: `
 | 
			
		||||
		{"podAntiAffinity": {
 | 
			
		||||
			"preferredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"weight": 5,
 | 
			
		||||
				"podAffinityTerm": {
 | 
			
		||||
					"labelSelector": {
 | 
			
		||||
						"matchExpressions": [{
 | 
			
		||||
							"key": "security",
 | 
			
		||||
							"operator": "In",
 | 
			
		||||
							"values":["S1"]
 | 
			
		||||
						}]
 | 
			
		||||
	antiAffinity1 := &v1.Affinity{
 | 
			
		||||
		PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
			PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{
 | 
			
		||||
				{
 | 
			
		||||
					Weight: 5,
 | 
			
		||||
					PodAffinityTerm: v1.PodAffinityTerm{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: "",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
					"namespaces": [],
 | 
			
		||||
					"topologyKey": ""
 | 
			
		||||
				}
 | 
			
		||||
			}]
 | 
			
		||||
		}}`,
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		pod            *v1.Pod
 | 
			
		||||
@@ -640,7 +657,7 @@ func TestSoftPodAntiAffinityWithFailureDomains(t *testing.T) {
 | 
			
		||||
		test           string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1, Annotations: antiAffinity1}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: antiAffinity1}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
@@ -654,7 +671,7 @@ func TestSoftPodAntiAffinityWithFailureDomains(t *testing.T) {
 | 
			
		||||
			test:           "Soft Pod Anti Affinity: when the topologyKey is emtpy, match among topologyKeys indicated by failure domains.",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1, Annotations: antiAffinity1}},
 | 
			
		||||
			pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: antiAffinity1}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
			pods: []*v1.Pod{
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
				{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: v1.ObjectMeta{Labels: podLabel1}},
 | 
			
		||||
 
 | 
			
		||||
@@ -38,18 +38,9 @@ func PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.Nod
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	annotationAffinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if annotationAffinity != nil {
 | 
			
		||||
		affinity.PodAffinity = annotationAffinity.PodAffinity
 | 
			
		||||
		affinity.PodAntiAffinity = annotationAffinity.PodAntiAffinity
 | 
			
		||||
	}
 | 
			
		||||
	return &priorityMetadata{
 | 
			
		||||
		nonZeroRequest: getNonZeroRequests(pod),
 | 
			
		||||
		podTolerations: tolerations,
 | 
			
		||||
		affinity:       affinity,
 | 
			
		||||
		affinity:       pod.Spec.Affinity,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -209,11 +209,8 @@ func (n *NodeInfo) String() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasPodAffinityConstraints(pod *v1.Pod) bool {
 | 
			
		||||
	affinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations)
 | 
			
		||||
	if err != nil || affinity == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil
 | 
			
		||||
	affinity := pod.Spec.Affinity
 | 
			
		||||
	return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addPod adds pod information to this NodeInfo.
 | 
			
		||||
 
 | 
			
		||||
@@ -175,9 +175,6 @@ func SetDefaults_PodSpec(obj *PodSpec) {
 | 
			
		||||
		period := int64(DefaultTerminationGracePeriodSeconds)
 | 
			
		||||
		obj.TerminationGracePeriodSeconds = &period
 | 
			
		||||
	}
 | 
			
		||||
	if obj.Affinity == nil {
 | 
			
		||||
		obj.Affinity = &Affinity{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func SetDefaults_Probe(obj *Probe) {
 | 
			
		||||
	if obj.TimeoutSeconds == 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,8 +44,7 @@ var masterNodes sets.String
 | 
			
		||||
 | 
			
		||||
type pausePodConfig struct {
 | 
			
		||||
	Name                              string
 | 
			
		||||
	Affinity                          string
 | 
			
		||||
	NodeAffinity                      *v1.Affinity
 | 
			
		||||
	Affinity                          *v1.Affinity
 | 
			
		||||
	Annotations, Labels, NodeSelector map[string]string
 | 
			
		||||
	Resources                         *v1.ResourceRequirements
 | 
			
		||||
}
 | 
			
		||||
@@ -241,7 +240,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		podName := "without-label"
 | 
			
		||||
		_, err := cs.Core().Pods(ns).Create(initPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: podName,
 | 
			
		||||
			NodeAffinity: &v1.Affinity{
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
@@ -303,7 +302,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
 | 
			
		||||
		createPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: podName,
 | 
			
		||||
			NodeAffinity: &v1.Affinity{
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
@@ -350,7 +349,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		labelPodName := "with-labels"
 | 
			
		||||
		pod := createPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: labelPodName,
 | 
			
		||||
			NodeAffinity: &v1.Affinity{
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
 | 
			
		||||
						NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
@@ -392,24 +391,24 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		_, err := cs.Core().Pods(ns).Create(initPausePod(f, pausePodConfig{
 | 
			
		||||
			Name:   podName,
 | 
			
		||||
			Labels: map[string]string{"name": "without-label"},
 | 
			
		||||
			Affinity: `{
 | 
			
		||||
				"podAffinity": {
 | 
			
		||||
					"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"weight": 0,
 | 
			
		||||
						"podAffinityTerm": {
 | 
			
		||||
							"labelSelector": {
 | 
			
		||||
								"matchExpressions": [{
 | 
			
		||||
									"key": "service",
 | 
			
		||||
									"operator": "DoesNotExist",
 | 
			
		||||
									"values":["securityscan"]
 | 
			
		||||
								}]
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				PodAffinity: &v1.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpDoesNotExist,
 | 
			
		||||
										Values:   []string{"securityscan"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: "kubernetes.io/hostname",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
							"namespaces": [],
 | 
			
		||||
							"topologyKey": "kubernetes.io/hostname"
 | 
			
		||||
						}
 | 
			
		||||
					}]
 | 
			
		||||
				 }
 | 
			
		||||
			}`,
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
		if err == nil || !errors.IsInvalid(err) {
 | 
			
		||||
@@ -427,20 +426,24 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		podName := "without-label-" + string(uuid.NewUUID())
 | 
			
		||||
		createPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: podName,
 | 
			
		||||
			Affinity: `{
 | 
			
		||||
				"podAffinity": {
 | 
			
		||||
					"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"labelSelector":{
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "service",
 | 
			
		||||
								"operator": "In",
 | 
			
		||||
								"values": ["securityscan", "value2"]
 | 
			
		||||
							}]
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				PodAffinity: &v1.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "service",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"securityscan", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: "kubernetes.io/hostname",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
						"topologyKey": "kubernetes.io/hostname"
 | 
			
		||||
					}]
 | 
			
		||||
				}
 | 
			
		||||
			}`,
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		waitForScheduler()
 | 
			
		||||
@@ -462,21 +465,25 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		labelPodName := "with-podaffinity-" + string(uuid.NewUUID())
 | 
			
		||||
		pod := createPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: labelPodName,
 | 
			
		||||
			Affinity: `{
 | 
			
		||||
				"podAffinity": {
 | 
			
		||||
					"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"labelSelector": {
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "In",
 | 
			
		||||
								"values": ["S1", "value2"]
 | 
			
		||||
							}]
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				PodAffinity: &v1.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S1", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: k,
 | 
			
		||||
							Namespaces:  []string{ns},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
						"topologyKey": "` + k + `",
 | 
			
		||||
						"namespaces":["` + ns + `"]
 | 
			
		||||
					}]
 | 
			
		||||
				}
 | 
			
		||||
			}`,
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		// check that pod got scheduled. We intentionally DO NOT check that the
 | 
			
		||||
@@ -529,21 +536,25 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
			Name:         labelPodName,
 | 
			
		||||
			Labels:       map[string]string{"service": "Diff"},
 | 
			
		||||
			NodeSelector: map[string]string{k: v}, // only launch on our two nodes, contradicting the podAntiAffinity
 | 
			
		||||
			Affinity: `{
 | 
			
		||||
				"podAntiAffinity": {
 | 
			
		||||
					"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"labelSelector":{
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "service",
 | 
			
		||||
								"operator": "In",
 | 
			
		||||
								"values": ["S1", "value2"]
 | 
			
		||||
							}]
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S1", "value2"},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: k,
 | 
			
		||||
							Namespaces:  []string{ns},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
						"topologyKey": "` + k + `",
 | 
			
		||||
						"namespaces": ["` + ns + `"]
 | 
			
		||||
					}]
 | 
			
		||||
				}
 | 
			
		||||
			}`,
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		waitForScheduler()
 | 
			
		||||
@@ -565,29 +576,31 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
		labelPodName := "with-podaffinity-" + string(uuid.NewUUID())
 | 
			
		||||
		pod := createPausePod(f, pausePodConfig{
 | 
			
		||||
			Name: labelPodName,
 | 
			
		||||
			Affinity: `{
 | 
			
		||||
				"podAffinity": {
 | 
			
		||||
					"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
						"labelSelector":{
 | 
			
		||||
							"matchExpressions": [{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "In",
 | 
			
		||||
								"values": ["S1", "value2"]
 | 
			
		||||
							},
 | 
			
		||||
			Affinity: &v1.Affinity{
 | 
			
		||||
				PodAffinity: &v1.PodAffinity{
 | 
			
		||||
					RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
						{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator": "NotIn",
 | 
			
		||||
								"values": ["S2"]
 | 
			
		||||
							},
 | 
			
		||||
							LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
								MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
									{
 | 
			
		||||
								"key": "security",
 | 
			
		||||
								"operator":"Exists"
 | 
			
		||||
							}]
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
										Values:   []string{"S1", "value2"},
 | 
			
		||||
									}, {
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpNotIn,
 | 
			
		||||
										Values:   []string{"S2"},
 | 
			
		||||
									}, {
 | 
			
		||||
										Key:      "security",
 | 
			
		||||
										Operator: metav1.LabelSelectorOpExists,
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							TopologyKey: k,
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
						"topologyKey": "` + k + `"
 | 
			
		||||
					}]
 | 
			
		||||
				}
 | 
			
		||||
			}`,
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		// check that pod got scheduled. We intentionally DO NOT check that the
 | 
			
		||||
@@ -745,15 +758,6 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod {
 | 
			
		||||
	if conf.Affinity != "" {
 | 
			
		||||
		if conf.Annotations == nil {
 | 
			
		||||
			conf.Annotations = map[string]string{
 | 
			
		||||
				v1.AffinityAnnotationKey: conf.Affinity,
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			conf.Annotations[v1.AffinityAnnotationKey] = conf.Affinity
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	pod := &v1.Pod{
 | 
			
		||||
		ObjectMeta: v1.ObjectMeta{
 | 
			
		||||
			Name:        conf.Name,
 | 
			
		||||
@@ -762,7 +766,7 @@ func initPausePod(f *framework.Framework, conf pausePodConfig) *v1.Pod {
 | 
			
		||||
		},
 | 
			
		||||
		Spec: v1.PodSpec{
 | 
			
		||||
			NodeSelector: conf.NodeSelector,
 | 
			
		||||
			Affinity:     conf.NodeAffinity,
 | 
			
		||||
			Affinity:     conf.Affinity,
 | 
			
		||||
			Containers: []v1.Container{
 | 
			
		||||
				{
 | 
			
		||||
					Name:  podName,
 | 
			
		||||
@@ -808,7 +812,7 @@ func runPodAndGetNodeName(f *framework.Framework, conf pausePodConfig) string {
 | 
			
		||||
func createPodWithNodeAffinity(f *framework.Framework) *v1.Pod {
 | 
			
		||||
	return createPausePod(f, pausePodConfig{
 | 
			
		||||
		Name: "with-nodeaffinity-" + string(uuid.NewUUID()),
 | 
			
		||||
		NodeAffinity: &v1.Affinity{
 | 
			
		||||
		Affinity: &v1.Affinity{
 | 
			
		||||
			NodeAffinity: &v1.NodeAffinity{
 | 
			
		||||
				RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
 | 
			
		||||
					NodeSelectorTerms: []v1.NodeSelectorTerm{
 | 
			
		||||
@@ -831,32 +835,40 @@ func createPodWithNodeAffinity(f *framework.Framework) *v1.Pod {
 | 
			
		||||
func createPodWithPodAffinity(f *framework.Framework, topologyKey string) *v1.Pod {
 | 
			
		||||
	return createPausePod(f, pausePodConfig{
 | 
			
		||||
		Name: "with-podantiaffinity-" + string(uuid.NewUUID()),
 | 
			
		||||
		Affinity: `{
 | 
			
		||||
			"podAffinity": {
 | 
			
		||||
				"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"labelSelector": {
 | 
			
		||||
					"matchExpressions": [{
 | 
			
		||||
						"key": "security",
 | 
			
		||||
						"operator": "In",
 | 
			
		||||
						"values":["S1"]
 | 
			
		||||
					}]
 | 
			
		||||
		Affinity: &v1.Affinity{
 | 
			
		||||
			PodAffinity: &v1.PodAffinity{
 | 
			
		||||
				RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
					{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S1"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: topologyKey,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			PodAntiAffinity: &v1.PodAntiAffinity{
 | 
			
		||||
				RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
 | 
			
		||||
					{
 | 
			
		||||
						LabelSelector: &metav1.LabelSelector{
 | 
			
		||||
							MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
			
		||||
								{
 | 
			
		||||
									Key:      "security",
 | 
			
		||||
									Operator: metav1.LabelSelectorOpIn,
 | 
			
		||||
									Values:   []string{"S2"},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
						TopologyKey: topologyKey,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				"topologyKey": "` + topologyKey + `"
 | 
			
		||||
				}]
 | 
			
		||||
			},
 | 
			
		||||
			"podAntiAffinity": {
 | 
			
		||||
				"requiredDuringSchedulingIgnoredDuringExecution": [{
 | 
			
		||||
				"labelSelector": {
 | 
			
		||||
					"matchExpressions": [{
 | 
			
		||||
						"key": "security",
 | 
			
		||||
						"operator": "In",
 | 
			
		||||
						"values":["S2"]
 | 
			
		||||
					}]
 | 
			
		||||
		},
 | 
			
		||||
				"topologyKey": "` + topologyKey + `"
 | 
			
		||||
				}]
 | 
			
		||||
			}
 | 
			
		||||
		}`,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user