From eccbd992da75861aec7b3a205b5b7c0a2a02b2e5 Mon Sep 17 00:00:00 2001 From: Avesh Agarwal Date: Wed, 22 Mar 2017 01:01:49 -0400 Subject: [PATCH] Add validation for taints annotations. --- pkg/api/helpers.go | 17 +++++++++++++++++ pkg/api/validation/validation.go | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pkg/api/helpers.go b/pkg/api/helpers.go index 1bc0318ee9e..faa7df7c0f4 100644 --- a/pkg/api/helpers.go +++ b/pkg/api/helpers.go @@ -434,6 +434,10 @@ const ( // in the Annotations of a Pod. TolerationsAnnotationKey string = "scheduler.alpha.kubernetes.io/tolerations" + // TaintsAnnotationKey represents the key of taints data (json serialized) + // in the Annotations of a Node. + TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints" + // SeccompPodAnnotationKey represents the key of a seccomp profile applied // to all containers of a pod. SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod" @@ -571,6 +575,19 @@ func (t *Taint) ToString() string { return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect) } +// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations +// and converts it to the []Taint type in api. +func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) { + var taints []Taint + if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" { + err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints) + if err != nil { + return []Taint{}, err + } + } + return taints, nil +} + // SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls // and a slice of unsafe Sysctls. This is only a convenience wrapper around // SysctlsFromPodAnnotation. diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 0293d1c0c35..1ca11e43043 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -2949,6 +2949,23 @@ func ValidateReadOnlyPersistentDisks(volumes []api.Volume, fldPath *field.Path) return allErrs } +// ValidateTaintsInNodeAnnotations tests that the serialized taints in Node.Annotations has valid data +func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + taints, err := api.GetTaintsFromNodeAnnotations(annotations) + if err != nil { + allErrs = append(allErrs, field.Invalid(fldPath, api.TaintsAnnotationKey, err.Error())) + return allErrs + } + + if len(taints) > 0 { + allErrs = append(allErrs, validateNodeTaints(taints, fldPath.Child(api.TaintsAnnotationKey))...) + } + + return allErrs +} + // validateNodeTaints tests if given taints have valid data. func validateNodeTaints(taints []api.Taint, fldPath *field.Path) field.ErrorList { allErrors := field.ErrorList{} @@ -2985,6 +3002,11 @@ func validateNodeTaints(taints []api.Taint, fldPath *field.Path) field.ErrorList func ValidateNodeSpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + + if annotations[api.TaintsAnnotationKey] != "" { + allErrs = append(allErrs, ValidateTaintsInNodeAnnotations(annotations, fldPath)...) + } + if annotations[api.PreferAvoidPodsAnnotationKey] != "" { allErrs = append(allErrs, ValidateAvoidPodsInNodeAnnotations(annotations, fldPath)...) }