From d2117c014881886e731776ffb630cd9178cde35e Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Tue, 11 Apr 2017 17:27:14 -0400 Subject: [PATCH 1/2] Fix to not allow when the feature AffinityInAnnotations is disabled. https://github.com/kubernetes/kubernetes/issues/44360 --- pkg/api/validation/BUILD | 1 + pkg/api/validation/validation.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/pkg/api/validation/BUILD b/pkg/api/validation/BUILD index b524bd28eb9..d6a819b4474 100644 --- a/pkg/api/validation/BUILD +++ b/pkg/api/validation/BUILD @@ -85,6 +85,7 @@ go_test( "//vendor:k8s.io/apimachinery/pkg/util/sets", "//vendor:k8s.io/apimachinery/pkg/util/validation/field", "//vendor:k8s.io/apimachinery/pkg/util/yaml", + "//vendor:k8s.io/apiserver/pkg/util/feature", ], ) diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 4dc0ce0aa18..09fd8a864f3 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -2213,6 +2213,9 @@ func ValidatePreferredSchedulingTerms(terms []api.PreferredSchedulingTerm, fldPa // validatePodAffinityTerm tests that the specified podAffinityTerm fields have valid data func validatePodAffinityTerm(podAffinityTerm api.PodAffinityTerm, allowEmptyTopologyKey bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + if !utilfeature.DefaultFeatureGate.Enabled(features.AffinityInAnnotations) && len(podAffinityTerm.TopologyKey) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("topologyKey"), "can not be empty")) + } allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(podAffinityTerm.LabelSelector, fldPath.Child("matchExpressions"))...) for _, name := range podAffinityTerm.Namespaces { for _, msg := range ValidateNamespaceName(name, false) { From ebe32554395c85b42ee34d7f5901a211bbf80cf1 Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Thu, 13 Apr 2017 15:03:30 -0400 Subject: [PATCH 2/2] Add unit tests when the feature AffinityInAnnotations is disabled. --- pkg/api/validation/validation_test.go | 119 ++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 72fa9bf7de1..ec46b1565a1 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/helper" "k8s.io/kubernetes/pkg/api/service" @@ -4316,6 +4317,124 @@ func TestValidatePod(t *testing.T) { } } +func TestValidatePodWithDisabledAffinityInAnnotations(t *testing.T) { + validPodSpec := func(affinity *api.Affinity) api.PodSpec { + spec := api.PodSpec{ + Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: api.RestartPolicyAlways, + DNSPolicy: api.DNSClusterFirst, + } + if affinity != nil { + spec.Affinity = affinity + } + return spec + } + + utilfeature.DefaultFeatureGate.Set("AffinityInAnnotations=False") + errorCases := []api.Pod{ + { + ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, + 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"}, + }, + }, + }, + TopologyKey: "", + Namespaces: []string{"ns"}, + }, + }, + }, + }), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, + Spec: validPodSpec(&api.Affinity{ + PodAffinity: &api.PodAffinity{ + 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: "", + }, + }, + }, + }, + }), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, + Spec: validPodSpec(&api.Affinity{ + PodAntiAffinity: &api.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "key2", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"value1", "value2"}, + }, + }, + }, + TopologyKey: "", + Namespaces: []string{"ns"}, + }, + }, + }, + }), + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, + Spec: validPodSpec(&api.Affinity{ + PodAntiAffinity: &api.PodAntiAffinity{ + 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: "", + }, + }, + }, + }, + }), + }, + } + + for _, v := range errorCases { + if errs := ValidatePod(&v); len(errs) == 0 { + t.Errorf("expected failure for %v", errs) + } + } +} + func TestValidatePodUpdate(t *testing.T) { var ( activeDeadlineSecondsZero = int64(0)