Commit 6a3ad93d authored by Robert Rati's avatar Robert Rati

[scheduling] Moved pod affinity and anti-affinity from annotations to api

fields. #25319
parent 1854d482
...@@ -486,20 +486,6 @@ const ( ...@@ -486,20 +486,6 @@ const (
UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls" 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 // GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
// and converts it to the []Toleration type in api. // and converts it to the []Toleration type in api.
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) { func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
......
...@@ -241,62 +241,6 @@ func TestNodeSelectorRequirementsAsSelector(t *testing.T) { ...@@ -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) { func TestTaintToString(t *testing.T) {
testCases := []struct { testCases := []struct {
taint *Taint taint *Taint
......
...@@ -331,7 +331,6 @@ func TestEncode_Ptr(t *testing.T) { ...@@ -331,7 +331,6 @@ func TestEncode_Ptr(t *testing.T) {
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
} }
obj := runtime.Object(pod) obj := runtime.Object(pod)
...@@ -345,7 +344,6 @@ func TestEncode_Ptr(t *testing.T) { ...@@ -345,7 +344,6 @@ func TestEncode_Ptr(t *testing.T) {
} }
if !api.Semantic.DeepEqual(obj2, pod) { 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)) 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 { ...@@ -29,7 +29,6 @@ func DeepEqualSafePodSpec() api.PodSpec {
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
} }
} }
......
...@@ -174,9 +174,6 @@ func SetDefaults_PodSpec(obj *PodSpec) { ...@@ -174,9 +174,6 @@ func SetDefaults_PodSpec(obj *PodSpec) {
period := int64(DefaultTerminationGracePeriodSeconds) period := int64(DefaultTerminationGracePeriodSeconds)
obj.TerminationGracePeriodSeconds = &period obj.TerminationGracePeriodSeconds = &period
} }
if obj.Affinity == nil {
obj.Affinity = &Affinity{}
}
} }
func SetDefaults_Probe(obj *Probe) { func SetDefaults_Probe(obj *Probe) {
if obj.TimeoutSeconds == 0 { if obj.TimeoutSeconds == 0 {
......
...@@ -101,10 +101,6 @@ func ValidateDNS1123Subdomain(value string, fldPath *field.Path) field.ErrorList ...@@ -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 { func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.PodSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if annotations[api.AffinityAnnotationKey] != "" {
allErrs = append(allErrs, ValidateAffinityInPodAnnotations(annotations, fldPath)...)
}
if annotations[api.TolerationsAnnotationKey] != "" { if annotations[api.TolerationsAnnotationKey] != "" {
allErrs = append(allErrs, ValidateTolerationsInPodAnnotations(annotations, fldPath)...) allErrs = append(allErrs, ValidateTolerationsInPodAnnotations(annotations, fldPath)...)
} }
...@@ -1672,7 +1668,14 @@ func validateAffinity(affinity *api.Affinity, fldPath *field.Path) field.ErrorLi ...@@ -1672,7 +1668,14 @@ func validateAffinity(affinity *api.Affinity, fldPath *field.Path) field.ErrorLi
allErrs = append(allErrs, ValidatePreferredSchedulingTerms(na.PreferredDuringSchedulingIgnoredDuringExecution, fldPath.Child("preferredDuringSchedulingIgnoredDuringExecution"))...) 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 return allErrs
} }
...@@ -1968,30 +1971,6 @@ func validatePodAffinity(podAffinity *api.PodAffinity, fldPath *field.Path) fiel ...@@ -1968,30 +1971,6 @@ func validatePodAffinity(podAffinity *api.PodAffinity, fldPath *field.Path) fiel
return allErrs 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 // ValidateTolerationsInPodAnnotations tests that the serialized tolerations in Pod.Annotations has valid data
func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
......
...@@ -40,7 +40,6 @@ func TestSetDefaultDaemonSet(t *testing.T) { ...@@ -40,7 +40,6 @@ func TestSetDefaultDaemonSet(t *testing.T) {
RestartPolicy: v1.RestartPolicyAlways, RestartPolicy: v1.RestartPolicyAlways,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
TerminationGracePeriodSeconds: &period, TerminationGracePeriodSeconds: &period,
Affinity: &v1.Affinity{},
}, },
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Labels: defaultLabels, Labels: defaultLabels,
...@@ -52,7 +51,6 @@ func TestSetDefaultDaemonSet(t *testing.T) { ...@@ -52,7 +51,6 @@ func TestSetDefaultDaemonSet(t *testing.T) {
RestartPolicy: v1.RestartPolicyAlways, RestartPolicy: v1.RestartPolicyAlways,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
TerminationGracePeriodSeconds: &period, TerminationGracePeriodSeconds: &period,
Affinity: &v1.Affinity{},
}, },
} }
tests := []struct { tests := []struct {
...@@ -157,7 +155,6 @@ func TestSetDefaultDeployment(t *testing.T) { ...@@ -157,7 +155,6 @@ func TestSetDefaultDeployment(t *testing.T) {
RestartPolicy: v1.RestartPolicyAlways, RestartPolicy: v1.RestartPolicyAlways,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
TerminationGracePeriodSeconds: &period, TerminationGracePeriodSeconds: &period,
Affinity: &v1.Affinity{},
}, },
} }
tests := []struct { tests := []struct {
......
...@@ -132,7 +132,6 @@ func TestMerge(t *testing.T) { ...@@ -132,7 +132,6 @@ func TestMerge(t *testing.T) {
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
}, },
}, },
......
...@@ -54,7 +54,6 @@ func TestDecodeSinglePod(t *testing.T) { ...@@ -54,7 +54,6 @@ func TestDecodeSinglePod(t *testing.T) {
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(),
}}, }},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
} }
json, err := runtime.Encode(testapi.Default.Codec(), pod) json, err := runtime.Encode(testapi.Default.Codec(), pod)
...@@ -115,7 +114,6 @@ func TestDecodePodList(t *testing.T) { ...@@ -115,7 +114,6 @@ func TestDecodePodList(t *testing.T) {
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(),
}}, }},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
} }
podList := &v1.PodList{ podList := &v1.PodList{
......
...@@ -188,7 +188,6 @@ func getTestCases(hostname types.NodeName) []*testCase { ...@@ -188,7 +188,6 @@ func getTestCases(hostname types.NodeName) []*testCase {
Spec: v1.PodSpec{ Spec: v1.PodSpec{
Containers: []v1.Container{{Name: "image", Image: "test/image", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}}, Containers: []v1.Container{{Name: "image", Image: "test/image", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
Status: v1.PodStatus{ Status: v1.PodStatus{
Phase: v1.PodPending, Phase: v1.PodPending,
...@@ -214,7 +213,6 @@ func getTestCases(hostname types.NodeName) []*testCase { ...@@ -214,7 +213,6 @@ func getTestCases(hostname types.NodeName) []*testCase {
ImagePullPolicy: "Always", ImagePullPolicy: "Always",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}}, SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
Status: v1.PodStatus{ Status: v1.PodStatus{
Phase: v1.PodPending, Phase: v1.PodPending,
......
...@@ -148,7 +148,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -148,7 +148,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
NodeName: string(nodeName), NodeName: string(nodeName),
Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}}, Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
Status: v1.PodStatus{ Status: v1.PodStatus{
Phase: v1.PodPending, Phase: v1.PodPending,
...@@ -170,7 +169,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -170,7 +169,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
DNSPolicy: v1.DNSClusterFirst, DNSPolicy: v1.DNSClusterFirst,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
Affinity: &v1.Affinity{},
Containers: []v1.Container{{ Containers: []v1.Container{{
Name: "1", Name: "1",
...@@ -201,7 +199,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -201,7 +199,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
NodeName: nodeName, NodeName: nodeName,
Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}}, Containers: []v1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1.PullAlways}},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
Status: v1.PodStatus{ Status: v1.PodStatus{
Phase: v1.PodPending, Phase: v1.PodPending,
...@@ -216,7 +213,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -216,7 +213,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
NodeName: nodeName, NodeName: nodeName,
Containers: []v1.Container{{Name: "2", Image: "bar:bartag", ImagePullPolicy: ""}}, Containers: []v1.Container{{Name: "2", Image: "bar:bartag", ImagePullPolicy: ""}},
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
}, },
Status: v1.PodStatus{ Status: v1.PodStatus{
Phase: v1.PodPending, Phase: v1.PodPending,
...@@ -240,7 +236,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -240,7 +236,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
DNSPolicy: v1.DNSClusterFirst, DNSPolicy: v1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
Containers: []v1.Container{{ Containers: []v1.Container{{
Name: "1", Name: "1",
...@@ -267,7 +262,6 @@ func TestExtractPodsFromHTTP(t *testing.T) { ...@@ -267,7 +262,6 @@ func TestExtractPodsFromHTTP(t *testing.T) {
DNSPolicy: v1.DNSClusterFirst, DNSPolicy: v1.DNSClusterFirst,
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &v1.PodSecurityContext{}, SecurityContext: &v1.PodSecurityContext{},
Affinity: &v1.Affinity{},
Containers: []v1.Container{{ Containers: []v1.Container{{
Name: "2", Name: "2",
......
...@@ -484,7 +484,8 @@ func TestCriticalPrioritySorting(t *testing.T) { ...@@ -484,7 +484,8 @@ func TestCriticalPrioritySorting(t *testing.T) {
Requests: v1.ResourceList{ Requests: v1.ResourceList{
"memory": resource.MustParse("90"), "memory": resource.MustParse("90"),
}, },
}}}} }}},
}
pods := []*v1.Pod{ pods := []*v1.Pod{
podWithUidNameNsSpec("000000000", "newpod", "foo", spec), podWithUidNameNsSpec("000000000", "newpod", "foo", spec),
podWithUidNameNsSpec("987654321", "oldpod", "foo", spec), podWithUidNameNsSpec("987654321", "oldpod", "foo", spec),
...@@ -637,7 +638,8 @@ func TestHandleMemExceeded(t *testing.T) { ...@@ -637,7 +638,8 @@ func TestHandleMemExceeded(t *testing.T) {
Requests: v1.ResourceList{ Requests: v1.ResourceList{
"memory": resource.MustParse("90"), "memory": resource.MustParse("90"),
}, },
}}}} }}},
}
pods := []*v1.Pod{ pods := []*v1.Pod{
podWithUidNameNsSpec("123456789", "newpod", "foo", spec), podWithUidNameNsSpec("123456789", "newpod", "foo", spec),
podWithUidNameNsSpec("987654321", "oldpod", "foo", spec), podWithUidNameNsSpec("987654321", "oldpod", "foo", spec),
......
...@@ -73,7 +73,6 @@ func validNewPod() *api.Pod { ...@@ -73,7 +73,6 @@ func validNewPod() *api.Pod {
}, },
}, },
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
} }
} }
...@@ -660,7 +659,6 @@ func TestEtcdUpdateScheduled(t *testing.T) { ...@@ -660,7 +659,6 @@ func TestEtcdUpdateScheduled(t *testing.T) {
}, },
}, },
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
}, nil, 1) }, nil, 1)
if err != nil { if err != nil {
...@@ -689,7 +687,6 @@ func TestEtcdUpdateScheduled(t *testing.T) { ...@@ -689,7 +687,6 @@ func TestEtcdUpdateScheduled(t *testing.T) {
TerminationGracePeriodSeconds: &grace, TerminationGracePeriodSeconds: &grace,
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
} }
_, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme)) _, _, err = storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn, api.Scheme))
...@@ -730,7 +727,6 @@ func TestEtcdUpdateStatus(t *testing.T) { ...@@ -730,7 +727,6 @@ func TestEtcdUpdateStatus(t *testing.T) {
}, },
}, },
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
} }
err := storage.Storage.Create(ctx, key, &podStart, nil, 0) err := storage.Storage.Create(ctx, key, &podStart, nil, 0)
...@@ -755,7 +751,6 @@ func TestEtcdUpdateStatus(t *testing.T) { ...@@ -755,7 +751,6 @@ func TestEtcdUpdateStatus(t *testing.T) {
}, },
}, },
SecurityContext: &api.PodSecurityContext{}, SecurityContext: &api.PodSecurityContext{},
Affinity: &api.Affinity{},
}, },
Status: api.PodStatus{ Status: api.PodStatus{
Phase: api.PodRunning, Phase: api.PodRunning,
......
...@@ -19,7 +19,6 @@ go_library( ...@@ -19,7 +19,6 @@ go_library(
"//pkg/admission:go_default_library", "//pkg/admission:go_default_library",
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/errors:go_default_library", "//pkg/api/errors:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
], ],
) )
......
...@@ -20,7 +20,6 @@ import ( ...@@ -20,7 +20,6 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
...@@ -56,11 +55,7 @@ func (p *plugin) Admit(attributes admission.Attributes) (err error) { ...@@ -56,11 +55,7 @@ func (p *plugin) Admit(attributes admission.Attributes) (err error) {
if !ok { if !ok {
return apierrors.NewBadRequest("Resource was marked with kind Pod but was unable to be converted") return apierrors.NewBadRequest("Resource was marked with kind Pod but was unable to be converted")
} }
affinity, err := api.GetAffinityFromPodAnnotations(pod.Annotations) affinity := pod.Spec.Affinity
if err != nil {
glog.V(5).Infof("Invalid Affinity detected, but we will leave handling of this to validation phase")
return nil
}
if affinity != nil && affinity.PodAntiAffinity != nil { if affinity != nil && affinity.PodAntiAffinity != nil {
var podAntiAffinityTerms []api.PodAffinityTerm var podAntiAffinityTerms []api.PodAffinityTerm
if len(affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 { if len(affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution) != 0 {
......
...@@ -32,109 +32,120 @@ func TestInterPodAffinityAdmission(t *testing.T) { ...@@ -32,109 +32,120 @@ func TestInterPodAffinityAdmission(t *testing.T) {
Spec: api.PodSpec{}, Spec: api.PodSpec{},
} }
tests := []struct { tests := []struct {
affinity map[string]string affinity *api.Affinity
errorExpected bool errorExpected bool
}{ }{
// empty affinity its success. // empty affinity its success.
{ {
affinity: map[string]string{}, affinity: &api.Affinity{},
errorExpected: false, errorExpected: false,
}, },
// what ever topologyKey in preferredDuringSchedulingIgnoredDuringExecution, the admission should success. // what ever topologyKey in preferredDuringSchedulingIgnoredDuringExecution, the admission should success.
{ {
affinity: map[string]string{ affinity: &api.Affinity{
api.AffinityAnnotationKey: ` PodAntiAffinity: &api.PodAntiAffinity{
{"podAntiAffinity": { PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
"preferredDuringSchedulingIgnoredDuringExecution": [{ {
"weight": 5, Weight: 5,
"podAffinityTerm": { PodAffinityTerm: api.PodAffinityTerm{
"labelSelector": { LabelSelector: &metav1.LabelSelector{
"matchExpressions": [{ MatchExpressions: []metav1.LabelSelectorRequirement{
"key": "security", {
"operator": "In", Key: "security",
"values":["S2"] Operator: metav1.LabelSelectorOpIn,
}] Values: []string{"S2"},
},
}, },
"namespaces": [], },
"topologyKey": "az" TopologyKey: "az",
} },
}] },
}}`, },
},
}, },
errorExpected: false, errorExpected: false,
}, },
// valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution, // valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution,
// plus any topologyKey in preferredDuringSchedulingIgnoredDuringExecution, then admission success. // plus any topologyKey in preferredDuringSchedulingIgnoredDuringExecution, then admission success.
{ {
affinity: map[string]string{ affinity: &api.Affinity{
api.AffinityAnnotationKey: ` PodAntiAffinity: &api.PodAntiAffinity{
{"podAntiAffinity": { PreferredDuringSchedulingIgnoredDuringExecution: []api.WeightedPodAffinityTerm{
"preferredDuringSchedulingIgnoredDuringExecution": [{ {
"weight": 5, Weight: 5,
"podAffinityTerm": { PodAffinityTerm: api.PodAffinityTerm{
"labelSelector": { LabelSelector: &metav1.LabelSelector{
"matchExpressions": [{ MatchExpressions: []metav1.LabelSelectorRequirement{
"key": "security", {
"operator": "In", Key: "security",
"values":["S2"] 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"},
},
}, },
"namespaces": [],
"topologyKey": "az"
}
}],
"requiredDuringSchedulingIgnoredDuringExecution": [{
"labelSelector": {
"matchExpressions": [{
"key": "security",
"operator": "In",
"values":["S2"]
}]
}, },
"namespaces": [], TopologyKey: metav1.LabelHostname,
"topologyKey": "` + metav1.LabelHostname + `" },
}] },
}}`, },
}, },
errorExpected: false, errorExpected: false,
}, },
// valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission success. // valid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission success.
{ {
affinity: map[string]string{ affinity: &api.Affinity{
api.AffinityAnnotationKey: ` PodAntiAffinity: &api.PodAntiAffinity{
{"podAntiAffinity": { RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
"requiredDuringSchedulingIgnoredDuringExecution": [{ {
"labelSelector": { LabelSelector: &metav1.LabelSelector{
"matchExpressions": [{ MatchExpressions: []metav1.LabelSelectorRequirement{
"key": "security", {
"operator": "In", Key: "security",
"values":["S2"] Operator: metav1.LabelSelectorOpIn,
}] Values: []string{"S2"},
},
},
}, },
"namespaces":[], TopologyKey: metav1.LabelHostname,
"topologyKey": "` + metav1.LabelHostname + `" },
}] },
}}`, },
}, },
errorExpected: false, errorExpected: false,
}, },
// invalid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission fails. // invalid topologyKey in requiredDuringSchedulingIgnoredDuringExecution then admission fails.
{ {
affinity: map[string]string{ affinity: &api.Affinity{
api.AffinityAnnotationKey: ` PodAntiAffinity: &api.PodAntiAffinity{
{"podAntiAffinity": { RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
"requiredDuringSchedulingIgnoredDuringExecution": [{ {
"labelSelector": { LabelSelector: &metav1.LabelSelector{
"matchExpressions": [{ MatchExpressions: []metav1.LabelSelectorRequirement{
"key": "security", {
"operator": "In", Key: "security",
"values":["S2"] Operator: metav1.LabelSelectorOpIn,
}] Values: []string{"S2"},
},
},
}, },
"namespaces":[], TopologyKey: " zone ",
"topologyKey": " zone " },
}] },
}}`, },
}, },
errorExpected: true, errorExpected: true,
}, },
...@@ -161,59 +172,51 @@ func TestInterPodAffinityAdmission(t *testing.T) { ...@@ -161,59 +172,51 @@ func TestInterPodAffinityAdmission(t *testing.T) {
// } // }
// list of requiredDuringSchedulingIgnoredDuringExecution middle element topologyKey is not valid. // list of requiredDuringSchedulingIgnoredDuringExecution middle element topologyKey is not valid.
{ {
affinity: map[string]string{ affinity: &api.Affinity{
api.AffinityAnnotationKey: ` PodAntiAffinity: &api.PodAntiAffinity{
{"podAntiAffinity": { RequiredDuringSchedulingIgnoredDuringExecution: []api.PodAffinityTerm{
"requiredDuringSchedulingIgnoredDuringExecution": [{
"labelSelector": {
"matchExpressions": [{
"key": "security",
"operator": "In",
"values":["S2"]
}]
},
"namespaces":[],
"topologyKey": "` + metav1.LabelHostname + `"
},
{ {
"labelSelector": { LabelSelector: &metav1.LabelSelector{
"matchExpressions": [{ MatchExpressions: []metav1.LabelSelectorRequirement{
"key": "security", {
"operator": "In", Key: "security",
"values":["S2"] Operator: metav1.LabelSelectorOpIn,
}] Values: []string{"S2"},
},
},
}, },
"namespaces":[], TopologyKey: metav1.LabelHostname,
"topologyKey": " zone " }, {
}, LabelSelector: &metav1.LabelSelector{
{ MatchExpressions: []metav1.LabelSelectorRequirement{
"labelSelector": { {
"matchExpressions": [{ Key: "security",
"key": "security", Operator: metav1.LabelSelectorOpIn,
"operator": "In", Values: []string{"S2"},
"values":["S2"] },
}] },
}, },
"namespaces": [], TopologyKey: " zone ",
"topologyKey": "` + metav1.LabelHostname + `" }, {
}] LabelSelector: &metav1.LabelSelector{
}}`, MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "security",
Operator: metav1.LabelSelectorOpIn,
Values: []string{"S2"},
},
},
},
TopologyKey: metav1.LabelHostname,
},
},
},
}, },
errorExpected: true, errorExpected: true,
}, },
{
affinity: map[string]string{
api.AffinityAnnotationKey: `
{"podAntiAffinity": {
"thisIsAInvalidAffinity": [{}
}}`,
},
// however, we should not get error here
errorExpected: false,
},
} }
for _, test := range tests { 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)) 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 { if test.errorExpected && err == nil {
......
...@@ -46,6 +46,7 @@ go_test( ...@@ -46,6 +46,7 @@ go_test(
"//plugin/pkg/scheduler/algorithm:go_default_library", "//plugin/pkg/scheduler/algorithm:go_default_library",
"//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library", "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
"//plugin/pkg/scheduler/schedulercache:go_default_library", "//plugin/pkg/scheduler/schedulercache:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/labels", "//vendor:k8s.io/apimachinery/pkg/labels",
], ],
) )
......
...@@ -904,10 +904,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta interface ...@@ -904,10 +904,7 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta interface
} }
// Now check if <pod> requirements will be satisfied on this node. // Now check if <pod> requirements will be satisfied on this node.
affinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations) affinity := pod.Spec.Affinity
if err != nil {
return false, nil, err
}
if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) { if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) {
return true, nil, nil return true, nil, nil
} }
...@@ -1008,11 +1005,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler ...@@ -1008,11 +1005,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler
} }
var nodeResult []matchingPodAntiAffinityTerm var nodeResult []matchingPodAntiAffinityTerm
for _, existingPod := range nodeInfo.PodsWithAffinity() { for _, existingPod := range nodeInfo.PodsWithAffinity() {
affinity, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations) affinity := existingPod.Spec.Affinity
if err != nil {
catchError(err)
return
}
if affinity == nil { if affinity == nil {
continue continue
} }
...@@ -1040,10 +1033,7 @@ func getMatchingAntiAffinityTerms(pod *v1.Pod, nodeInfoMap map[string]*scheduler ...@@ -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) { func (c *PodAffinityChecker) getMatchingAntiAffinityTerms(pod *v1.Pod, allPods []*v1.Pod) ([]matchingPodAntiAffinityTerm, error) {
var result []matchingPodAntiAffinityTerm var result []matchingPodAntiAffinityTerm
for _, existingPod := range allPods { for _, existingPod := range allPods {
affinity, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations) affinity := pod.Spec.Affinity
if err != nil {
return nil, err
}
if affinity != nil && affinity.PodAntiAffinity != nil { if affinity != nil && affinity.PodAntiAffinity != nil {
existingPodNode, err := c.info.GetNodeInfo(existingPod.Spec.NodeName) existingPodNode, err := c.info.GetNodeInfo(existingPod.Spec.NodeName)
if err != nil { if err != nil {
......
...@@ -118,10 +118,7 @@ func (p *podAffinityPriorityMap) processTerms(terms []v1.WeightedPodAffinityTerm ...@@ -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 preferredDuringSchedulingIgnoredDuringExecution from podAffinity & podAntiAffinity,
// symmetry need to be considered for hard requirements from podAffinity // 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) { func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) {
affinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations) affinity := pod.Spec.Affinity
if err != nil {
return nil, err
}
hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil
hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil
...@@ -142,10 +139,7 @@ func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, node ...@@ -142,10 +139,7 @@ func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, node
if err != nil { if err != nil {
return err return err
} }
existingPodAffinity, err := v1.GetAffinityFromPodAnnotations(existingPod.Annotations) existingPodAffinity := existingPod.Spec.Affinity
if err != nil {
return err
}
existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil
existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil
......
...@@ -38,18 +38,9 @@ func PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.Nod ...@@ -38,18 +38,9 @@ func PriorityMetadata(pod *v1.Pod, nodeNameToInfo map[string]*schedulercache.Nod
if err != nil { if err != nil {
return 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{ return &priorityMetadata{
nonZeroRequest: getNonZeroRequests(pod), nonZeroRequest: getNonZeroRequests(pod),
podTolerations: tolerations, podTolerations: tolerations,
affinity: affinity, affinity: pod.Spec.Affinity,
} }
} }
...@@ -209,11 +209,8 @@ func (n *NodeInfo) String() string { ...@@ -209,11 +209,8 @@ func (n *NodeInfo) String() string {
} }
func hasPodAffinityConstraints(pod *v1.Pod) bool { func hasPodAffinityConstraints(pod *v1.Pod) bool {
affinity, err := v1.GetAffinityFromPodAnnotations(pod.Annotations) affinity := pod.Spec.Affinity
if err != nil || affinity == nil { return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil)
return false
}
return affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil
} }
// addPod adds pod information to this NodeInfo. // addPod adds pod information to this NodeInfo.
......
...@@ -175,9 +175,6 @@ func SetDefaults_PodSpec(obj *PodSpec) { ...@@ -175,9 +175,6 @@ func SetDefaults_PodSpec(obj *PodSpec) {
period := int64(DefaultTerminationGracePeriodSeconds) period := int64(DefaultTerminationGracePeriodSeconds)
obj.TerminationGracePeriodSeconds = &period obj.TerminationGracePeriodSeconds = &period
} }
if obj.Affinity == nil {
obj.Affinity = &Affinity{}
}
} }
func SetDefaults_Probe(obj *Probe) { func SetDefaults_Probe(obj *Probe) {
if obj.TimeoutSeconds == 0 { if obj.TimeoutSeconds == 0 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment