diff --git a/pkg/api/helpers.go b/pkg/api/helpers.go index 943a9ea9ae3..1bc0318ee9e 100644 --- a/pkg/api/helpers.go +++ b/pkg/api/helpers.go @@ -430,6 +430,10 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S } const ( + // TolerationsAnnotationKey represents the key of tolerations data (json serialized) + // in the Annotations of a Pod. + TolerationsAnnotationKey string = "scheduler.alpha.kubernetes.io/tolerations" + // SeccompPodAnnotationKey represents the key of a seccomp profile applied // to all containers of a pod. SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod" @@ -471,6 +475,19 @@ const ( AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity" ) +// 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) { + var tolerations []Toleration + if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" { + err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations) + if err != nil { + return tolerations, err + } + } + return tolerations, nil +} + // AddOrUpdateTolerationInPod tries to add a toleration to the pod's toleration list. // Returns true if something was updated, false otherwise. func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) (bool, error) { diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 1e360749ab9..0293d1c0c35 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -109,6 +109,10 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.Pod allErrs = append(allErrs, ValidateAffinityInPodAnnotations(annotations, fldPath)...) } + if annotations[api.TolerationsAnnotationKey] != "" { + allErrs = append(allErrs, ValidateTolerationsInPodAnnotations(annotations, fldPath)...) + } + // TODO: remove these after we EOL the annotations. if hostname, exists := annotations[utilpod.PodHostnameAnnotation]; exists { allErrs = append(allErrs, ValidateDNS1123Label(hostname, fldPath.Key(utilpod.PodHostnameAnnotation))...) @@ -140,6 +144,23 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.Pod 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{} + + tolerations, err := api.GetTolerationsFromPodAnnotations(annotations) + if err != nil { + allErrs = append(allErrs, field.Invalid(fldPath, api.TolerationsAnnotationKey, err.Error())) + return allErrs + } + + if len(tolerations) > 0 { + allErrs = append(allErrs, validateTolerations(tolerations, fldPath.Child(api.TolerationsAnnotationKey))...) + } + + 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{}