Update go dependencies
This commit is contained in:
parent
060e449056
commit
4fb61c73d1
1192 changed files with 185874 additions and 302749 deletions
284
vendor/k8s.io/kubernetes/pkg/api/validation/validation.go
generated
vendored
284
vendor/k8s.io/kubernetes/pkg/api/validation/validation.go
generated
vendored
|
|
@ -20,8 +20,8 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
|
@ -29,6 +29,9 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"math"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
|
|
@ -44,7 +47,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
apiservice "k8s.io/kubernetes/pkg/api/service"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
|
|
@ -107,10 +110,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 value, isMirror := annotations[api.MirrorPodAnnotationKey]; isMirror {
|
||||
if len(spec.NodeName) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(api.MirrorPodAnnotationKey), value, "must set spec.nodeName if mirror pod annotation is set"))
|
||||
|
|
@ -161,23 +160,6 @@ func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath
|
|||
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 := helper.GetAffinityFromPodAnnotations(annotations)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, api.AffinityAnnotationKey, err.Error()))
|
||||
return allErrs
|
||||
}
|
||||
if affinity == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validateAffinity(affinity, fldPath.Child("affinity"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidatePodSpecificAnnotationUpdates(newPod, oldPod *api.Pod, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
newAnnotations := newPod.Annotations
|
||||
|
|
@ -294,6 +276,10 @@ var ValidateClusterName = genericvalidation.ValidateClusterName
|
|||
// (where it should be) and this file.
|
||||
var ValidateClassName = NameIsDNSSubdomain
|
||||
|
||||
// ValidatePiorityClassName can be used to check whether the given priority
|
||||
// class name is valid.
|
||||
var ValidatePriorityClassName = NameIsDNSSubdomain
|
||||
|
||||
// TODO update all references to these functions to point to the genericvalidation ones
|
||||
// NameIsDNSSubdomain is a ValidateNameFunc for names that must be a DNS subdomain.
|
||||
func NameIsDNSSubdomain(name string, prefix bool) []string {
|
||||
|
|
@ -396,7 +382,12 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
|
|||
allErrs := field.ErrorList{}
|
||||
if source.EmptyDir != nil {
|
||||
numVolumes++
|
||||
// EmptyDirs have nothing to validate
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
|
||||
unsetSizeLimit := resource.Quantity{}
|
||||
if unsetSizeLimit.Cmp(source.EmptyDir.SizeLimit) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field disabled by feature-gate for EmptyDir volumes"))
|
||||
}
|
||||
}
|
||||
}
|
||||
if source.HostPath != nil {
|
||||
if numVolumes > 0 {
|
||||
|
|
@ -584,6 +575,14 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
|
|||
allErrs = append(allErrs, validateAzureDisk(source.AzureDisk, fldPath.Child("azureDisk"))...)
|
||||
}
|
||||
}
|
||||
if source.StorageOS != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("storageos"), "may not specify more than 1 volume type"))
|
||||
} else {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateStorageOSVolumeSource(source.StorageOS, fldPath.Child("storageos"))...)
|
||||
}
|
||||
}
|
||||
if source.Projected != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("projected"), "may not specify more than 1 volume type"))
|
||||
|
|
@ -612,7 +611,10 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource, fldPath *f
|
|||
allErrs := field.ErrorList{}
|
||||
if len(hostPath.Path) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validatePathNoBacksteps(hostPath.Path, fldPath.Child("path"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
@ -806,7 +808,8 @@ var validDownwardAPIFieldPathExpressions = sets.NewString(
|
|||
"metadata.name",
|
||||
"metadata.namespace",
|
||||
"metadata.labels",
|
||||
"metadata.annotations")
|
||||
"metadata.annotations",
|
||||
"metadata.uid")
|
||||
|
||||
func validateDownwardAPIVolumeFile(file *api.DownwardAPIVolumeFile, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
|
@ -943,8 +946,18 @@ func validateLocalDescendingPath(targetPath string, fldPath *field.Path) field.E
|
|||
allErrs = append(allErrs, field.Invalid(fldPath, targetPath, "must be a relative path"))
|
||||
}
|
||||
|
||||
// TODO: this assumes the OS of apiserver & nodes are the same
|
||||
parts := strings.Split(targetPath, string(os.PathSeparator))
|
||||
allErrs = append(allErrs, validatePathNoBacksteps(targetPath, fldPath)...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validatePathNoBacksteps makes sure the targetPath does not have any `..` path elements when split
|
||||
//
|
||||
// This assumes the OS of the apiserver and the nodes are the same. The same check should be done
|
||||
// on the node to ensure there are no backsteps.
|
||||
func validatePathNoBacksteps(targetPath string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
parts := strings.Split(filepath.ToSlash(targetPath), "/")
|
||||
for _, item := range parts {
|
||||
if item == ".." {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, targetPath, "must not contain '..'"))
|
||||
|
|
@ -1101,6 +1114,56 @@ func validateScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, fldPath *field.Pa
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func validateLocalVolumeSource(ls *api.LocalVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if ls.Path == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validatePathNoBacksteps(ls.Path, fldPath.Child("path"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateStorageOSVolumeSource(storageos *api.StorageOSVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(storageos.VolumeName) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("volumeName"), ""))
|
||||
} else {
|
||||
allErrs = append(allErrs, ValidateDNS1123Label(storageos.VolumeName, fldPath.Child("volumeName"))...)
|
||||
}
|
||||
if len(storageos.VolumeNamespace) > 0 {
|
||||
allErrs = append(allErrs, ValidateDNS1123Label(storageos.VolumeNamespace, fldPath.Child("volumeNamespace"))...)
|
||||
}
|
||||
if storageos.SecretRef != nil {
|
||||
if len(storageos.SecretRef.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), ""))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateStorageOSPersistentVolumeSource(storageos *api.StorageOSPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(storageos.VolumeName) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("volumeName"), ""))
|
||||
} else {
|
||||
allErrs = append(allErrs, ValidateDNS1123Label(storageos.VolumeName, fldPath.Child("volumeName"))...)
|
||||
}
|
||||
if len(storageos.VolumeNamespace) > 0 {
|
||||
allErrs = append(allErrs, ValidateDNS1123Label(storageos.VolumeNamespace, fldPath.Child("volumeNamespace"))...)
|
||||
}
|
||||
if storageos.SecretRef != nil {
|
||||
if len(storageos.SecretRef.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "name"), ""))
|
||||
}
|
||||
if len(storageos.SecretRef.Namespace) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("secretRef", "namespace"), ""))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
||||
// PersistentVolumeName object.
|
||||
var ValidatePersistentVolumeName = NameIsDNSSubdomain
|
||||
|
|
@ -1110,7 +1173,8 @@ var supportedAccessModes = sets.NewString(string(api.ReadWriteOnce), string(api.
|
|||
var supportedReclaimPolicy = sets.NewString(string(api.PersistentVolumeReclaimDelete), string(api.PersistentVolumeReclaimRecycle), string(api.PersistentVolumeReclaimRetain))
|
||||
|
||||
func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
||||
allErrs := ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName, field.NewPath("metadata"))
|
||||
metaPath := field.NewPath("metadata")
|
||||
allErrs := ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName, metaPath)
|
||||
|
||||
specPath := field.NewPath("spec")
|
||||
if len(pv.Spec.AccessModes) == 0 {
|
||||
|
|
@ -1139,6 +1203,9 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||
}
|
||||
}
|
||||
|
||||
nodeAffinitySpecified, errs := validateStorageNodeAffinityAnnotation(pv.ObjectMeta.Annotations, metaPath.Child("annotations"))
|
||||
allErrs = append(allErrs, errs...)
|
||||
|
||||
numVolumes := 0
|
||||
if pv.Spec.HostPath != nil {
|
||||
if numVolumes > 0 {
|
||||
|
|
@ -1290,6 +1357,30 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||
allErrs = append(allErrs, validateScaleIOVolumeSource(pv.Spec.ScaleIO, specPath.Child("scaleIO"))...)
|
||||
}
|
||||
}
|
||||
if pv.Spec.Local != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("local"), "may not specify more than 1 volume type"))
|
||||
} else {
|
||||
numVolumes++
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PersistentLocalVolumes) {
|
||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("local"), "Local volumes are disabled by feature-gate"))
|
||||
}
|
||||
allErrs = append(allErrs, validateLocalVolumeSource(pv.Spec.Local, specPath.Child("local"))...)
|
||||
|
||||
// NodeAffinity is required
|
||||
if !nodeAffinitySpecified {
|
||||
allErrs = append(allErrs, field.Required(metaPath.Child("annotations"), "Local volume requires node affinity"))
|
||||
}
|
||||
}
|
||||
}
|
||||
if pv.Spec.StorageOS != nil {
|
||||
if numVolumes > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("storageos"), "may not specify more than 1 volume type"))
|
||||
} else {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateStorageOSPersistentVolumeSource(pv.Spec.StorageOS, specPath.Child("storageos"))...)
|
||||
}
|
||||
}
|
||||
|
||||
if numVolumes == 0 {
|
||||
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
|
||||
|
|
@ -1365,7 +1456,7 @@ func ValidatePersistentVolumeClaimSpec(spec *api.PersistentVolumeClaimSpec, fldP
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeClaimUpdate validates an update to a PeristentVolumeClaim
|
||||
// ValidatePersistentVolumeClaimUpdate validates an update to a PersistentVolumeClaim
|
||||
func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *api.PersistentVolumeClaim) field.ErrorList {
|
||||
allErrs := ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidatePersistentVolumeClaim(newPvc)...)
|
||||
|
|
@ -1391,7 +1482,7 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *api.PersistentVolumeCla
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeClaimStatusUpdate validates an update to status of a PeristentVolumeClaim
|
||||
// ValidatePersistentVolumeClaimStatusUpdate validates an update to status of a PersistentVolumeClaim
|
||||
func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *api.PersistentVolumeClaim) field.ErrorList {
|
||||
allErrs := ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta, field.NewPath("metadata"))
|
||||
if len(newPvc.ResourceVersion) == 0 {
|
||||
|
|
@ -1448,6 +1539,7 @@ func validateContainerPorts(ports []api.ContainerPort, fldPath *field.Path) fiel
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateEnv validates env vars
|
||||
func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
|
|
@ -1465,7 +1557,7 @@ func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
|
|||
return allErrs
|
||||
}
|
||||
|
||||
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP")
|
||||
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP")
|
||||
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "requests.cpu", "requests.memory")
|
||||
|
||||
func validateEnvVarValueFrom(ev api.EnvVar, fldPath *field.Path) field.ErrorList {
|
||||
|
|
@ -1618,8 +1710,9 @@ func validateContainerResourceDivisor(rName string, divisor resource.Quantity, f
|
|||
func validateConfigMapKeySelector(s *api.ConfigMapKeySelector, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(s.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
nameFn := ValidateNameFunc(ValidateSecretName)
|
||||
for _, msg := range nameFn(s.Name, false) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), s.Name, msg))
|
||||
}
|
||||
if len(s.Key) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("key"), ""))
|
||||
|
|
@ -1635,8 +1728,9 @@ func validateConfigMapKeySelector(s *api.ConfigMapKeySelector, fldPath *field.Pa
|
|||
func validateSecretKeySelector(s *api.SecretKeySelector, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(s.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
nameFn := ValidateNameFunc(ValidateSecretName)
|
||||
for _, msg := range nameFn(s.Name, false) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), s.Name, msg))
|
||||
}
|
||||
if len(s.Key) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("key"), ""))
|
||||
|
|
@ -1666,6 +1760,9 @@ func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath
|
|||
if mountpoints.Has(mnt.MountPath) {
|
||||
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be unique"))
|
||||
}
|
||||
if !path.IsAbs(mnt.MountPath) {
|
||||
allErrs = append(allErrs, field.Invalid(idxPath.Child("mountPath"), mnt.MountPath, "must be an absolute path"))
|
||||
}
|
||||
mountpoints.Insert(mnt.MountPath)
|
||||
if len(mnt.SubPath) > 0 {
|
||||
allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...)
|
||||
|
|
@ -1882,6 +1979,9 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
|
|||
} else {
|
||||
allNames.Insert(ctr.Name)
|
||||
}
|
||||
// TODO: do not validate leading and trailing whitespace to preserve backward compatibility.
|
||||
// for example: https://github.com/openshift/origin/issues/14659 image = " " is special token in pod template
|
||||
// others may have done similar
|
||||
if len(ctr.Image) == 0 {
|
||||
allErrs = append(allErrs, field.Required(idxPath.Child("image"), ""))
|
||||
}
|
||||
|
|
@ -1905,6 +2005,7 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
|
|||
allErrs = append(allErrs, validateProbe(ctr.ReadinessProbe, idxPath.Child("readinessProbe"))...)
|
||||
allErrs = append(allErrs, validateContainerPorts(ctr.Ports, idxPath.Child("ports"))...)
|
||||
allErrs = append(allErrs, ValidateEnv(ctr.Env, idxPath.Child("env"))...)
|
||||
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, idxPath.Child("envFrom"))...)
|
||||
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volumes, idxPath.Child("volumeMounts"))...)
|
||||
allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, idxPath.Child("imagePullPolicy"))...)
|
||||
allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, idxPath.Child("resources"))...)
|
||||
|
|
@ -2070,7 +2171,7 @@ func ValidateHostAliases(hostAliases []api.HostAlias, fldPath *field.Path) field
|
|||
allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), hostAlias.IP, "must be valid IP address"))
|
||||
}
|
||||
for _, hostname := range hostAlias.Hostnames {
|
||||
allErrs = append(allErrs, ValidateDNS1123Label(hostname, fldPath.Child("hostnames"))...)
|
||||
allErrs = append(allErrs, ValidateDNS1123Subdomain(hostname, fldPath.Child("hostnames"))...)
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
|
|
@ -2121,12 +2222,33 @@ func ValidateTolerations(tolerations []api.Toleration, fldPath *field.Path) fiel
|
|||
return allErrors
|
||||
}
|
||||
|
||||
// validateContainersOnlyForPod does additional validation for containers on a pod versus a pod template
|
||||
// it only does additive validation of fields not covered in validateContainers
|
||||
func validateContainersOnlyForPod(containers []api.Container, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for i, ctr := range containers {
|
||||
idxPath := fldPath.Index(i)
|
||||
if len(ctr.Image) != len(strings.TrimSpace(ctr.Image)) {
|
||||
allErrs = append(allErrs, field.Invalid(idxPath.Child("image"), ctr.Image, "must not have leading or trailing whitespace"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePod tests if required fields in the pod are set.
|
||||
func ValidatePod(pod *api.Pod) field.ErrorList {
|
||||
fldPath := field.NewPath("metadata")
|
||||
allErrs := ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName, fldPath)
|
||||
allErrs = append(allErrs, ValidatePodSpecificAnnotations(pod.ObjectMeta.Annotations, &pod.Spec, fldPath.Child("annotations"))...)
|
||||
allErrs = append(allErrs, ValidatePodSpec(&pod.Spec, field.NewPath("spec"))...)
|
||||
|
||||
// we do additional validation only pertinent for pods and not pod templates
|
||||
// this was done to preserve backwards compatibility
|
||||
specPath := field.NewPath("spec")
|
||||
|
||||
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.Containers, specPath.Child("containers"))...)
|
||||
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.InitContainers, specPath.Child("initContainers"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
@ -2160,8 +2282,9 @@ func ValidatePodSpec(spec *api.PodSpec, fldPath *field.Path) field.ErrorList {
|
|||
}
|
||||
|
||||
if spec.ActiveDeadlineSeconds != nil {
|
||||
if *spec.ActiveDeadlineSeconds <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("activeDeadlineSeconds"), spec.ActiveDeadlineSeconds, "must be greater than 0"))
|
||||
value := *spec.ActiveDeadlineSeconds
|
||||
if value < 1 || value > math.MaxInt32 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("activeDeadlineSeconds"), value, validation.InclusiveRangeError(1, math.MaxInt32)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2181,6 +2304,20 @@ func ValidatePodSpec(spec *api.PodSpec, fldPath *field.Path) field.ErrorList {
|
|||
allErrs = append(allErrs, ValidateHostAliases(spec.HostAliases, fldPath.Child("hostAliases"))...)
|
||||
}
|
||||
|
||||
if len(spec.PriorityClassName) > 0 {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("priorityClassName"), "Pod priority is disabled by feature-gate"))
|
||||
} else {
|
||||
for _, msg := range ValidatePriorityClassName(spec.PriorityClassName, false) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("priorityClassName"), spec.PriorityClassName, msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if spec.Priority != nil && !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("priority"), "Pod priority is disabled by feature-gate"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
@ -2247,7 +2384,7 @@ func ValidateAvoidPodsInNodeAnnotations(annotations map[string]string, fldPath *
|
|||
return allErrs
|
||||
}
|
||||
var avoids api.AvoidPods
|
||||
if err := v1.Convert_v1_AvoidPods_To_api_AvoidPods(&v1Avoids, &avoids, nil); err != nil {
|
||||
if err := k8s_api_v1.Convert_v1_AvoidPods_To_api_AvoidPods(&v1Avoids, &avoids, nil); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("AvoidPods"), api.PreferAvoidPodsAnnotationKey, err.Error()))
|
||||
return allErrs
|
||||
}
|
||||
|
|
@ -2294,9 +2431,7 @@ 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) {
|
||||
|
|
@ -2514,6 +2649,10 @@ func ValidateContainerUpdates(newContainers, oldContainers []api.Container, fldP
|
|||
if len(ctr.Image) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("image"), ""))
|
||||
}
|
||||
// this is only called from ValidatePodUpdate so its safe to check leading/trailing whitespace.
|
||||
if len(strings.TrimSpace(ctr.Image)) != len(ctr.Image) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("image"), ctr.Image, "must not have leading or trailing whitespace"))
|
||||
}
|
||||
}
|
||||
return allErrs, false
|
||||
}
|
||||
|
|
@ -2547,8 +2686,8 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) field.ErrorList {
|
|||
// 2. from a positive value to a lesser, non-negative value
|
||||
if newPod.Spec.ActiveDeadlineSeconds != nil {
|
||||
newActiveDeadlineSeconds := *newPod.Spec.ActiveDeadlineSeconds
|
||||
if newActiveDeadlineSeconds < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(specPath.Child("activeDeadlineSeconds"), newActiveDeadlineSeconds, isNegativeErrorMsg))
|
||||
if newActiveDeadlineSeconds < 0 || newActiveDeadlineSeconds > math.MaxInt32 {
|
||||
allErrs = append(allErrs, field.Invalid(specPath.Child("activeDeadlineSeconds"), newActiveDeadlineSeconds, validation.InclusiveRangeError(0, math.MaxInt32)))
|
||||
return allErrs
|
||||
}
|
||||
if oldPod.Spec.ActiveDeadlineSeconds != nil {
|
||||
|
|
@ -2774,6 +2913,22 @@ func ValidateService(service *api.Service) field.ErrorList {
|
|||
nodePorts[key] = true
|
||||
}
|
||||
|
||||
// Check for duplicate TargetPort
|
||||
portsPath = specPath.Child("ports")
|
||||
targetPorts := make(map[api.ServicePort]bool)
|
||||
for i, port := range service.Spec.Ports {
|
||||
if (port.TargetPort.Type == intstr.Int && port.TargetPort.IntVal == 0) || (port.TargetPort.Type == intstr.String && port.TargetPort.StrVal == "") {
|
||||
continue
|
||||
}
|
||||
portPath := portsPath.Index(i)
|
||||
key := api.ServicePort{Protocol: port.Protocol, TargetPort: port.TargetPort}
|
||||
_, found := targetPorts[key]
|
||||
if found {
|
||||
allErrs = append(allErrs, field.Duplicate(portPath.Child("targetPort"), port.TargetPort))
|
||||
}
|
||||
targetPorts[key] = true
|
||||
}
|
||||
|
||||
// Validate SourceRange field and annotation
|
||||
_, ok := service.Annotations[api.AnnotationLoadBalancerSourceRangesKey]
|
||||
if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok {
|
||||
|
|
@ -2865,10 +3020,10 @@ func validateServiceExternalTrafficFieldsValue(service *api.Service) field.Error
|
|||
|
||||
// Check first class fields.
|
||||
if service.Spec.ExternalTrafficPolicy != "" &&
|
||||
service.Spec.ExternalTrafficPolicy != api.ServiceExternalTrafficPolicyTypeGlobal &&
|
||||
service.Spec.ExternalTrafficPolicy != api.ServiceExternalTrafficPolicyTypeCluster &&
|
||||
service.Spec.ExternalTrafficPolicy != api.ServiceExternalTrafficPolicyTypeLocal {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("externalTrafficPolicy"), service.Spec.ExternalTrafficPolicy,
|
||||
fmt.Sprintf("ExternalTrafficPolicy must be empty, %v or %v", api.ServiceExternalTrafficPolicyTypeGlobal, api.ServiceExternalTrafficPolicyTypeLocal)))
|
||||
fmt.Sprintf("ExternalTrafficPolicy must be empty, %v or %v", api.ServiceExternalTrafficPolicyTypeCluster, api.ServiceExternalTrafficPolicyTypeLocal)))
|
||||
}
|
||||
if service.Spec.HealthCheckNodePort < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("healthCheckNodePort"), service.Spec.HealthCheckNodePort,
|
||||
|
|
@ -3263,6 +3418,7 @@ func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
|||
// Refer to docs/design/resources.md for more details.
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !helper.IsStandardContainerResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||
|
|
@ -3605,6 +3761,9 @@ func ValidateResourceRequirements(requirements *api.ResourceRequirements, fldPat
|
|||
allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName)))
|
||||
}
|
||||
}
|
||||
if resourceName == api.ResourceStorageOverlay && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
|
||||
allErrs = append(allErrs, field.Forbidden(limPath, "ResourceStorageOverlay field disabled by feature-gate for ResourceRequirements"))
|
||||
}
|
||||
}
|
||||
for resourceName, quantity := range requirements.Requests {
|
||||
fldPath := reqPath.Key(string(resourceName))
|
||||
|
|
@ -3873,13 +4032,11 @@ func validateEndpointSubsets(subsets []api.EndpointSubset, oldSubsets []api.Endp
|
|||
ss := &subsets[i]
|
||||
idxPath := fldPath.Index(i)
|
||||
|
||||
// EndpointSubsets must include endpoint address. For headless service, we allow its endpoints not to have ports.
|
||||
if len(ss.Addresses) == 0 && len(ss.NotReadyAddresses) == 0 {
|
||||
//TODO: consider adding a RequiredOneOf() error for this and similar cases
|
||||
allErrs = append(allErrs, field.Required(idxPath, "must specify `addresses` or `notReadyAddresses`"))
|
||||
}
|
||||
if len(ss.Ports) == 0 {
|
||||
allErrs = append(allErrs, field.Required(idxPath.Child("ports"), ""))
|
||||
}
|
||||
for addr := range ss.Addresses {
|
||||
allErrs = append(allErrs, validateEndpointAddress(&ss.Addresses[addr], idxPath.Child("addresses").Index(addr), ipToNodeName)...)
|
||||
}
|
||||
|
|
@ -4044,3 +4201,32 @@ func sysctlIntersection(a []api.Sysctl, b []api.Sysctl) []string {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// validateStorageNodeAffinityAnnotation tests that the serialized TopologyConstraints in PersistentVolume.Annotations has valid data
|
||||
func validateStorageNodeAffinityAnnotation(annotations map[string]string, fldPath *field.Path) (bool, field.ErrorList) {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
na, err := helper.GetStorageNodeAffinityFromAnnotation(annotations)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, api.AlphaStorageNodeAffinityAnnotation, err.Error()))
|
||||
return false, allErrs
|
||||
}
|
||||
if na == nil {
|
||||
return false, allErrs
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PersistentLocalVolumes) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, "Storage node affinity is disabled by feature-gate"))
|
||||
}
|
||||
|
||||
policySpecified := false
|
||||
if na.RequiredDuringSchedulingIgnoredDuringExecution != nil {
|
||||
allErrs = append(allErrs, ValidateNodeSelector(na.RequiredDuringSchedulingIgnoredDuringExecution, fldPath.Child("requiredDuringSchedulingIgnoredDuringExecution"))...)
|
||||
policySpecified = true
|
||||
}
|
||||
|
||||
if len(na.PreferredDuringSchedulingIgnoredDuringExecution) > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("preferredDuringSchedulingIgnoredDuringExection"), "Storage node affinity does not support preferredDuringSchedulingIgnoredDuringExecution"))
|
||||
}
|
||||
return policySpecified, allErrs
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue