mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Move extensions validation to apps
This commit is contained in:
		@@ -18,12 +18,15 @@ package validation
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
						apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
				
			||||||
	apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 | 
						apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
 | 
						unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/labels"
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/intstr"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/validation"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
						"k8s.io/apimachinery/pkg/util/validation/field"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/apps"
 | 
						"k8s.io/kubernetes/pkg/apis/apps"
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						api "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
@@ -236,3 +239,433 @@ func ValidateControllerRevisionUpdate(newHistory, oldHistory *apps.ControllerRev
 | 
				
			|||||||
	errs = append(errs, apivalidation.ValidateImmutableField(newHistory.Data, oldHistory.Data, field.NewPath("data"))...)
 | 
						errs = append(errs, apivalidation.ValidateImmutableField(newHistory.Data, oldHistory.Data, field.NewPath("data"))...)
 | 
				
			||||||
	return errs
 | 
						return errs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateDaemonSet tests if required fields in the DaemonSet are set.
 | 
				
			||||||
 | 
					func ValidateDaemonSet(ds *apps.DaemonSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMeta(&ds.ObjectMeta, true, ValidateDaemonSetName, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateDaemonSetUpdate tests if required fields in the DaemonSet are set.
 | 
				
			||||||
 | 
					func ValidateDaemonSetUpdate(ds, oldDS *apps.DaemonSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDaemonSetSpecUpdate(&ds.Spec, &oldDS.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDaemonSetSpecUpdate(newSpec, oldSpec *apps.DaemonSetSpec, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TemplateGeneration shouldn't be decremented
 | 
				
			||||||
 | 
						if newSpec.TemplateGeneration < oldSpec.TemplateGeneration {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must not be decremented"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TemplateGeneration should be increased when and only when template is changed
 | 
				
			||||||
 | 
						templateUpdated := !apiequality.Semantic.DeepEqual(newSpec.Template, oldSpec.Template)
 | 
				
			||||||
 | 
						if newSpec.TemplateGeneration == oldSpec.TemplateGeneration && templateUpdated {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must be incremented upon template update"))
 | 
				
			||||||
 | 
						} else if newSpec.TemplateGeneration > oldSpec.TemplateGeneration && !templateUpdated {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must not be incremented without template update"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// validateDaemonSetStatus validates a DaemonSetStatus
 | 
				
			||||||
 | 
					func validateDaemonSetStatus(status *apps.DaemonSetStatus, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.CurrentNumberScheduled), fldPath.Child("currentNumberScheduled"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberMisscheduled), fldPath.Child("numberMisscheduled"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.DesiredNumberScheduled), fldPath.Child("desiredNumberScheduled"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberReady), fldPath.Child("numberReady"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(status.ObservedGeneration, fldPath.Child("observedGeneration"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UpdatedNumberScheduled), fldPath.Child("updatedNumberScheduled"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberAvailable), fldPath.Child("numberAvailable"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberUnavailable), fldPath.Child("numberUnavailable"))...)
 | 
				
			||||||
 | 
						if status.CollisionCount != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.CollisionCount), fldPath.Child("collisionCount"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section
 | 
				
			||||||
 | 
					func ValidateDaemonSetStatusUpdate(ds, oldDS *apps.DaemonSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, validateDaemonSetStatus(&ds.Status, field.NewPath("status"))...)
 | 
				
			||||||
 | 
						if apivalidation.IsDecremented(ds.Status.CollisionCount, oldDS.Status.CollisionCount) {
 | 
				
			||||||
 | 
							value := int32(0)
 | 
				
			||||||
 | 
							if ds.Status.CollisionCount != nil {
 | 
				
			||||||
 | 
								value = *ds.Status.CollisionCount
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(field.NewPath("status").Child("collisionCount"), value, "cannot be decremented"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set.
 | 
				
			||||||
 | 
					func ValidateDaemonSetSpec(spec *apps.DaemonSetSpec, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
				
			||||||
 | 
						if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if spec.Selector != nil && len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for daemonset"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...)
 | 
				
			||||||
 | 
						// Daemons typically run on more than one node, so mark Read-Write persistent disks as invalid.
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes, fldPath.Child("template", "spec", "volumes"))...)
 | 
				
			||||||
 | 
						// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
 | 
				
			||||||
 | 
						if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if spec.Template.Spec.ActiveDeadlineSeconds != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "spec", "activeDeadlineSeconds"), spec.Template.Spec.ActiveDeadlineSeconds, "must not be specified"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.TemplateGeneration), fldPath.Child("templateGeneration"))...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDaemonSetUpdateStrategy(&spec.UpdateStrategy, fldPath.Child("updateStrategy"))...)
 | 
				
			||||||
 | 
						if spec.RevisionHistoryLimit != nil {
 | 
				
			||||||
 | 
							// zero is a valid RevisionHistoryLimit
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateRollingUpdateDaemonSet(rollingUpdate *apps.RollingUpdateDaemonSet, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
				
			||||||
 | 
						if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 {
 | 
				
			||||||
 | 
							// MaxUnavailable cannot be 0.
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "cannot be 0"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Validate that MaxUnavailable is not more than 100%.
 | 
				
			||||||
 | 
						allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDaemonSetUpdateStrategy(strategy *apps.DaemonSetUpdateStrategy, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						switch strategy.Type {
 | 
				
			||||||
 | 
						case apps.OnDeleteDaemonSetStrategyType:
 | 
				
			||||||
 | 
						case apps.RollingUpdateDaemonSetStrategyType:
 | 
				
			||||||
 | 
							// Make sure RollingUpdate field isn't nil.
 | 
				
			||||||
 | 
							if strategy.RollingUpdate == nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Required(fldPath.Child("rollingUpdate"), ""))
 | 
				
			||||||
 | 
								return allErrs
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, ValidateRollingUpdateDaemonSet(strategy.RollingUpdate, fldPath.Child("rollingUpdate"))...)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							validValues := []string{string(apps.RollingUpdateDaemonSetStrategyType), string(apps.OnDeleteDaemonSetStrategyType)}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath, strategy, validValues))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateDaemonSetName can be used to check whether the given daemon set name is valid.
 | 
				
			||||||
 | 
					// Prefix indicates this name will be used as part of generation, in which case
 | 
				
			||||||
 | 
					// trailing dashes are allowed.
 | 
				
			||||||
 | 
					var ValidateDaemonSetName = apimachineryvalidation.NameIsDNSSubdomain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validates that the given name can be used as a deployment name.
 | 
				
			||||||
 | 
					var ValidateDeploymentName = apimachineryvalidation.NameIsDNSSubdomain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						switch intOrPercent.Type {
 | 
				
			||||||
 | 
						case intstr.String:
 | 
				
			||||||
 | 
							for _, msg := range validation.IsValidPercent(intOrPercent.StrVal) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, msg))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case intstr.Int:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(intOrPercent.IntValue()), fldPath)...)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, "must be an integer or percentage (e.g '5%%')"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getPercentValue(intOrStringValue intstr.IntOrString) (int, bool) {
 | 
				
			||||||
 | 
						if intOrStringValue.Type != intstr.String {
 | 
				
			||||||
 | 
							return 0, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(validation.IsValidPercent(intOrStringValue.StrVal)) != 0 {
 | 
				
			||||||
 | 
							return 0, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						value, _ := strconv.Atoi(intOrStringValue.StrVal[:len(intOrStringValue.StrVal)-1])
 | 
				
			||||||
 | 
						return value, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getIntOrPercentValue(intOrStringValue intstr.IntOrString) int {
 | 
				
			||||||
 | 
						value, isPercent := getPercentValue(intOrStringValue)
 | 
				
			||||||
 | 
						if isPercent {
 | 
				
			||||||
 | 
							return value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return intOrStringValue.IntValue()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						value, isPercent := getPercentValue(intOrStringValue)
 | 
				
			||||||
 | 
						if !isPercent || value <= 100 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, field.Invalid(fldPath, intOrStringValue, "must not be greater than 100%"))
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateRollingUpdateDeployment(rollingUpdate *apps.RollingUpdateDeployment, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
 | 
				
			||||||
 | 
						if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 && getIntOrPercentValue(rollingUpdate.MaxSurge) == 0 {
 | 
				
			||||||
 | 
							// Both MaxSurge and MaxUnavailable cannot be zero.
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "may not be 0 when `maxSurge` is 0"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Validate that MaxUnavailable is not more than 100%.
 | 
				
			||||||
 | 
						allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDeploymentStrategy(strategy *apps.DeploymentStrategy, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						switch strategy.Type {
 | 
				
			||||||
 | 
						case apps.RecreateDeploymentStrategyType:
 | 
				
			||||||
 | 
							if strategy.RollingUpdate != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Forbidden(fldPath.Child("rollingUpdate"), "may not be specified when strategy `type` is '"+string(apps.RecreateDeploymentStrategyType+"'")))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case apps.RollingUpdateDeploymentStrategyType:
 | 
				
			||||||
 | 
							// This should never happen since it's set and checked in defaults.go
 | 
				
			||||||
 | 
							if strategy.RollingUpdate == nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Required(fldPath.Child("rollingUpdate"), "this should be defaulted and never be nil"))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, fldPath.Child("rollingUpdate"))...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							validValues := []string{string(apps.RecreateDeploymentStrategyType), string(apps.RollingUpdateDeploymentStrategyType)}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath, strategy, validValues))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateRollback(rollback *apps.RollbackConfig, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						v := rollback.Revision
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(v), fldPath.Child("version"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validates given deployment spec.
 | 
				
			||||||
 | 
					func ValidateDeploymentSpec(spec *apps.DeploymentSpec, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if spec.Selector == nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
				
			||||||
 | 
							if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for deployment"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector"))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, fldPath.Child("strategy"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
				
			||||||
 | 
						if spec.RevisionHistoryLimit != nil {
 | 
				
			||||||
 | 
							// zero is a valid RevisionHistoryLimit
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if spec.RollbackTo != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, ValidateRollback(spec.RollbackTo, fldPath.Child("rollback"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if spec.ProgressDeadlineSeconds != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ProgressDeadlineSeconds), fldPath.Child("progressDeadlineSeconds"))...)
 | 
				
			||||||
 | 
							if *spec.ProgressDeadlineSeconds <= spec.MinReadySeconds {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("progressDeadlineSeconds"), spec.ProgressDeadlineSeconds, "must be greater than minReadySeconds"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validates given deployment status.
 | 
				
			||||||
 | 
					func ValidateDeploymentStatus(status *apps.DeploymentStatus, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(status.ObservedGeneration, fldPath.Child("observedGeneration"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Replicas), fldPath.Child("replicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UpdatedReplicas), fldPath.Child("updatedReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ReadyReplicas), fldPath.Child("readyReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.AvailableReplicas), fldPath.Child("availableReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UnavailableReplicas), fldPath.Child("unavailableReplicas"))...)
 | 
				
			||||||
 | 
						if status.CollisionCount != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.CollisionCount), fldPath.Child("collisionCount"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						msg := "cannot be greater than status.replicas"
 | 
				
			||||||
 | 
						if status.UpdatedReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("updatedReplicas"), status.UpdatedReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.ReadyReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("readyReplicas"), status.ReadyReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.AvailableReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.AvailableReplicas > status.ReadyReplicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, "cannot be greater than readyReplicas"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDeploymentUpdate(update, old *apps.Deployment) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDeploymentSpec(&update.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDeploymentStatusUpdate(update, old *apps.Deployment) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						fldPath := field.NewPath("status")
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDeploymentStatus(&update.Status, fldPath)...)
 | 
				
			||||||
 | 
						if apivalidation.IsDecremented(update.Status.CollisionCount, old.Status.CollisionCount) {
 | 
				
			||||||
 | 
							value := int32(0)
 | 
				
			||||||
 | 
							if update.Status.CollisionCount != nil {
 | 
				
			||||||
 | 
								value = *update.Status.CollisionCount
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("collisionCount"), value, "cannot be decremented"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDeployment(obj *apps.Deployment) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateDeploymentName, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateDeploymentSpec(&obj.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateDeploymentRollback(obj *apps.DeploymentRollback) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateAnnotations(obj.UpdatedAnnotations, field.NewPath("updatedAnnotations"))
 | 
				
			||||||
 | 
						if len(obj.Name) == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(field.NewPath("name"), "name is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateRollback(&obj.RollbackTo, field.NewPath("rollback"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReplicaSetName can be used to check whether the given ReplicaSet
 | 
				
			||||||
 | 
					// name is valid.
 | 
				
			||||||
 | 
					// Prefix indicates this name will be used as part of generation, in which case
 | 
				
			||||||
 | 
					// trailing dashes are allowed.
 | 
				
			||||||
 | 
					var ValidateReplicaSetName = apimachineryvalidation.NameIsDNSSubdomain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReplicaSet tests if required fields in the ReplicaSet are set.
 | 
				
			||||||
 | 
					func ValidateReplicaSet(rs *apps.ReplicaSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := apivalidation.ValidateObjectMeta(&rs.ObjectMeta, true, ValidateReplicaSetName, field.NewPath("metadata"))
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateReplicaSetSpec(&rs.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReplicaSetUpdate tests if required fields in the ReplicaSet are set.
 | 
				
			||||||
 | 
					func ValidateReplicaSetUpdate(rs, oldRs *apps.ReplicaSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&rs.ObjectMeta, &oldRs.ObjectMeta, field.NewPath("metadata"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateReplicaSetSpec(&rs.Spec, field.NewPath("spec"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReplicaSetStatusUpdate tests if required fields in the ReplicaSet are set.
 | 
				
			||||||
 | 
					func ValidateReplicaSetStatusUpdate(rs, oldRs *apps.ReplicaSet) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&rs.ObjectMeta, &oldRs.ObjectMeta, field.NewPath("metadata"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateReplicaSetStatus(rs.Status, field.NewPath("status"))...)
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateReplicaSetStatus(status apps.ReplicaSetStatus, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Replicas), fldPath.Child("replicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.FullyLabeledReplicas), fldPath.Child("fullyLabeledReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ReadyReplicas), fldPath.Child("readyReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.AvailableReplicas), fldPath.Child("availableReplicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ObservedGeneration), fldPath.Child("observedGeneration"))...)
 | 
				
			||||||
 | 
						msg := "cannot be greater than status.replicas"
 | 
				
			||||||
 | 
						if status.FullyLabeledReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("fullyLabeledReplicas"), status.FullyLabeledReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.ReadyReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("readyReplicas"), status.ReadyReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.AvailableReplicas > status.Replicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, msg))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if status.AvailableReplicas > status.ReadyReplicas {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, "cannot be greater than readyReplicas"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateReplicaSetSpec tests if required fields in the ReplicaSet spec are set.
 | 
				
			||||||
 | 
					func ValidateReplicaSetSpec(spec *apps.ReplicaSetSpec, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...)
 | 
				
			||||||
 | 
						allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if spec.Selector == nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
				
			||||||
 | 
							if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for deployment"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector"))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validates the given template and ensures that it is in accordance with the desired selector and replicas.
 | 
				
			||||||
 | 
					func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selector labels.Selector, replicas int32, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						if template == nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath, ""))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if !selector.Empty() {
 | 
				
			||||||
 | 
								// Verify that the ReplicaSet selector matches the labels in template.
 | 
				
			||||||
 | 
								labels := labels.Set(template.Labels)
 | 
				
			||||||
 | 
								if !selector.Matches(labels) {
 | 
				
			||||||
 | 
									allErrs = append(allErrs, field.Invalid(fldPath.Child("metadata", "labels"), template.Labels, "`selector` does not match template `labels`"))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(template, fldPath)...)
 | 
				
			||||||
 | 
							if replicas > 1 {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(template.Spec.Volumes, fldPath.Child("spec", "volumes"))...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
 | 
				
			||||||
 | 
							if template.Spec.RestartPolicy != api.RestartPolicyAlways {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)}))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if template.Spec.ActiveDeadlineSeconds != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("spec", "activeDeadlineSeconds"), template.Spec.ActiveDeadlineSeconds, "must not be specified"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -19,347 +19,15 @@ package validation
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiequality "k8s.io/apimachinery/pkg/api/equality"
 | 
					 | 
				
			||||||
	apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 | 
						apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
					 | 
				
			||||||
	unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/labels"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/intstr"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/validation"
 | 
						"k8s.io/apimachinery/pkg/util/validation"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
						"k8s.io/apimachinery/pkg/util/validation/field"
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
					 | 
				
			||||||
	apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
 | 
						apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/extensions"
 | 
						"k8s.io/kubernetes/pkg/apis/extensions"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidateDaemonSet tests if required fields in the DaemonSet are set.
 | 
					 | 
				
			||||||
func ValidateDaemonSet(ds *extensions.DaemonSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMeta(&ds.ObjectMeta, true, ValidateDaemonSetName, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateDaemonSetUpdate tests if required fields in the DaemonSet are set.
 | 
					 | 
				
			||||||
func ValidateDaemonSetUpdate(ds, oldDS *extensions.DaemonSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDaemonSetSpecUpdate(&ds.Spec, &oldDS.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDaemonSetSpec(&ds.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDaemonSetSpecUpdate(newSpec, oldSpec *extensions.DaemonSetSpec, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TemplateGeneration shouldn't be decremented
 | 
					 | 
				
			||||||
	if newSpec.TemplateGeneration < oldSpec.TemplateGeneration {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must not be decremented"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TemplateGeneration should be increased when and only when template is changed
 | 
					 | 
				
			||||||
	templateUpdated := !apiequality.Semantic.DeepEqual(newSpec.Template, oldSpec.Template)
 | 
					 | 
				
			||||||
	if newSpec.TemplateGeneration == oldSpec.TemplateGeneration && templateUpdated {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must be incremented upon template update"))
 | 
					 | 
				
			||||||
	} else if newSpec.TemplateGeneration > oldSpec.TemplateGeneration && !templateUpdated {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("templateGeneration"), newSpec.TemplateGeneration, "must not be incremented without template update"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// validateDaemonSetStatus validates a DaemonSetStatus
 | 
					 | 
				
			||||||
func validateDaemonSetStatus(status *extensions.DaemonSetStatus, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.CurrentNumberScheduled), fldPath.Child("currentNumberScheduled"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberMisscheduled), fldPath.Child("numberMisscheduled"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.DesiredNumberScheduled), fldPath.Child("desiredNumberScheduled"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberReady), fldPath.Child("numberReady"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(status.ObservedGeneration, fldPath.Child("observedGeneration"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UpdatedNumberScheduled), fldPath.Child("updatedNumberScheduled"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberAvailable), fldPath.Child("numberAvailable"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.NumberUnavailable), fldPath.Child("numberUnavailable"))...)
 | 
					 | 
				
			||||||
	if status.CollisionCount != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.CollisionCount), fldPath.Child("collisionCount"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section
 | 
					 | 
				
			||||||
func ValidateDaemonSetStatusUpdate(ds, oldDS *extensions.DaemonSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMetaUpdate(&ds.ObjectMeta, &oldDS.ObjectMeta, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, validateDaemonSetStatus(&ds.Status, field.NewPath("status"))...)
 | 
					 | 
				
			||||||
	if apivalidation.IsDecremented(ds.Status.CollisionCount, oldDS.Status.CollisionCount) {
 | 
					 | 
				
			||||||
		value := int32(0)
 | 
					 | 
				
			||||||
		if ds.Status.CollisionCount != nil {
 | 
					 | 
				
			||||||
			value = *ds.Status.CollisionCount
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(field.NewPath("status").Child("collisionCount"), value, "cannot be decremented"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set.
 | 
					 | 
				
			||||||
func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
					 | 
				
			||||||
	if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if spec.Selector != nil && len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for daemonset"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...)
 | 
					 | 
				
			||||||
	// Daemons typically run on more than one node, so mark Read-Write persistent disks as invalid.
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes, fldPath.Child("template", "spec", "volumes"))...)
 | 
					 | 
				
			||||||
	// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
 | 
					 | 
				
			||||||
	if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)}))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if spec.Template.Spec.ActiveDeadlineSeconds != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "spec", "activeDeadlineSeconds"), spec.Template.Spec.ActiveDeadlineSeconds, "must not be specified"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.TemplateGeneration), fldPath.Child("templateGeneration"))...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDaemonSetUpdateStrategy(&spec.UpdateStrategy, fldPath.Child("updateStrategy"))...)
 | 
					 | 
				
			||||||
	if spec.RevisionHistoryLimit != nil {
 | 
					 | 
				
			||||||
		// zero is a valid RevisionHistoryLimit
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateRollingUpdateDaemonSet(rollingUpdate *extensions.RollingUpdateDaemonSet, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
					 | 
				
			||||||
	if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 {
 | 
					 | 
				
			||||||
		// MaxUnavailable cannot be 0.
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "cannot be 0"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Validate that MaxUnavailable is not more than 100%.
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDaemonSetUpdateStrategy(strategy *extensions.DaemonSetUpdateStrategy, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	switch strategy.Type {
 | 
					 | 
				
			||||||
	case extensions.OnDeleteDaemonSetStrategyType:
 | 
					 | 
				
			||||||
	case extensions.RollingUpdateDaemonSetStrategyType:
 | 
					 | 
				
			||||||
		// Make sure RollingUpdate field isn't nil.
 | 
					 | 
				
			||||||
		if strategy.RollingUpdate == nil {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Required(fldPath.Child("rollingUpdate"), ""))
 | 
					 | 
				
			||||||
			return allErrs
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, ValidateRollingUpdateDaemonSet(strategy.RollingUpdate, fldPath.Child("rollingUpdate"))...)
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		validValues := []string{string(extensions.RollingUpdateDaemonSetStrategyType), string(extensions.OnDeleteDaemonSetStrategyType)}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.NotSupported(fldPath, strategy, validValues))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateDaemonSetName can be used to check whether the given daemon set name is valid.
 | 
					 | 
				
			||||||
// Prefix indicates this name will be used as part of generation, in which case
 | 
					 | 
				
			||||||
// trailing dashes are allowed.
 | 
					 | 
				
			||||||
var ValidateDaemonSetName = apimachineryvalidation.NameIsDNSSubdomain
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Validates that the given name can be used as a deployment name.
 | 
					 | 
				
			||||||
var ValidateDeploymentName = apimachineryvalidation.NameIsDNSSubdomain
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidatePositiveIntOrPercent(intOrPercent intstr.IntOrString, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	switch intOrPercent.Type {
 | 
					 | 
				
			||||||
	case intstr.String:
 | 
					 | 
				
			||||||
		for _, msg := range validation.IsValidPercent(intOrPercent.StrVal) {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, msg))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case intstr.Int:
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(intOrPercent.IntValue()), fldPath)...)
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath, intOrPercent, "must be an integer or percentage (e.g '5%%')"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getPercentValue(intOrStringValue intstr.IntOrString) (int, bool) {
 | 
					 | 
				
			||||||
	if intOrStringValue.Type != intstr.String {
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(validation.IsValidPercent(intOrStringValue.StrVal)) != 0 {
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	value, _ := strconv.Atoi(intOrStringValue.StrVal[:len(intOrStringValue.StrVal)-1])
 | 
					 | 
				
			||||||
	return value, true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getIntOrPercentValue(intOrStringValue intstr.IntOrString) int {
 | 
					 | 
				
			||||||
	value, isPercent := getPercentValue(intOrStringValue)
 | 
					 | 
				
			||||||
	if isPercent {
 | 
					 | 
				
			||||||
		return value
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return intOrStringValue.IntValue()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func IsNotMoreThan100Percent(intOrStringValue intstr.IntOrString, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	value, isPercent := getPercentValue(intOrStringValue)
 | 
					 | 
				
			||||||
	if !isPercent || value <= 100 {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, field.Invalid(fldPath, intOrStringValue, "must not be greater than 100%"))
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateRollingUpdateDeployment(rollingUpdate *extensions.RollingUpdateDeployment, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
 | 
					 | 
				
			||||||
	if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 && getIntOrPercentValue(rollingUpdate.MaxSurge) == 0 {
 | 
					 | 
				
			||||||
		// Both MaxSurge and MaxUnavailable cannot be zero.
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "may not be 0 when `maxSurge` is 0"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Validate that MaxUnavailable is not more than 100%.
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDeploymentStrategy(strategy *extensions.DeploymentStrategy, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	switch strategy.Type {
 | 
					 | 
				
			||||||
	case extensions.RecreateDeploymentStrategyType:
 | 
					 | 
				
			||||||
		if strategy.RollingUpdate != nil {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Forbidden(fldPath.Child("rollingUpdate"), "may not be specified when strategy `type` is '"+string(extensions.RecreateDeploymentStrategyType+"'")))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case extensions.RollingUpdateDeploymentStrategyType:
 | 
					 | 
				
			||||||
		// This should never happen since it's set and checked in defaults.go
 | 
					 | 
				
			||||||
		if strategy.RollingUpdate == nil {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Required(fldPath.Child("rollingUpdate"), "this should be defaulted and never be nil"))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, fldPath.Child("rollingUpdate"))...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		validValues := []string{string(extensions.RecreateDeploymentStrategyType), string(extensions.RollingUpdateDeploymentStrategyType)}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.NotSupported(fldPath, strategy, validValues))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateRollback(rollback *extensions.RollbackConfig, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	v := rollback.Revision
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(v), fldPath.Child("version"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Validates given deployment spec.
 | 
					 | 
				
			||||||
func ValidateDeploymentSpec(spec *extensions.DeploymentSpec, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if spec.Selector == nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
					 | 
				
			||||||
		if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for deployment"))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector"))
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, fldPath.Child("strategy"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
					 | 
				
			||||||
	if spec.RevisionHistoryLimit != nil {
 | 
					 | 
				
			||||||
		// zero is a valid RevisionHistoryLimit
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if spec.RollbackTo != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, ValidateRollback(spec.RollbackTo, fldPath.Child("rollback"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if spec.ProgressDeadlineSeconds != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ProgressDeadlineSeconds), fldPath.Child("progressDeadlineSeconds"))...)
 | 
					 | 
				
			||||||
		if *spec.ProgressDeadlineSeconds <= spec.MinReadySeconds {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Invalid(fldPath.Child("progressDeadlineSeconds"), spec.ProgressDeadlineSeconds, "must be greater than minReadySeconds"))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Validates given deployment status.
 | 
					 | 
				
			||||||
func ValidateDeploymentStatus(status *extensions.DeploymentStatus, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(status.ObservedGeneration, fldPath.Child("observedGeneration"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Replicas), fldPath.Child("replicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UpdatedReplicas), fldPath.Child("updatedReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ReadyReplicas), fldPath.Child("readyReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.AvailableReplicas), fldPath.Child("availableReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UnavailableReplicas), fldPath.Child("unavailableReplicas"))...)
 | 
					 | 
				
			||||||
	if status.CollisionCount != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*status.CollisionCount), fldPath.Child("collisionCount"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	msg := "cannot be greater than status.replicas"
 | 
					 | 
				
			||||||
	if status.UpdatedReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("updatedReplicas"), status.UpdatedReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.ReadyReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("readyReplicas"), status.ReadyReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.AvailableReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.AvailableReplicas > status.ReadyReplicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, "cannot be greater than readyReplicas"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDeploymentUpdate(update, old *extensions.Deployment) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDeploymentSpec(&update.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDeploymentStatusUpdate(update, old *extensions.Deployment) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	fldPath := field.NewPath("status")
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDeploymentStatus(&update.Status, fldPath)...)
 | 
					 | 
				
			||||||
	if apivalidation.IsDecremented(update.Status.CollisionCount, old.Status.CollisionCount) {
 | 
					 | 
				
			||||||
		value := int32(0)
 | 
					 | 
				
			||||||
		if update.Status.CollisionCount != nil {
 | 
					 | 
				
			||||||
			value = *update.Status.CollisionCount
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("collisionCount"), value, "cannot be decremented"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDeployment(obj *extensions.Deployment) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateDeploymentName, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateDeploymentSpec(&obj.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateDeploymentRollback(obj *extensions.DeploymentRollback) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateAnnotations(obj.UpdatedAnnotations, field.NewPath("updatedAnnotations"))
 | 
					 | 
				
			||||||
	if len(obj.Name) == 0 {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Required(field.NewPath("name"), "name is required"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateRollback(&obj.RollbackTo, field.NewPath("rollback"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateIngress tests if required fields in the Ingress are set.
 | 
					// ValidateIngress tests if required fields in the Ingress are set.
 | 
				
			||||||
func ValidateIngress(ingress *extensions.Ingress) field.ErrorList {
 | 
					func ValidateIngress(ingress *extensions.Ingress) field.ErrorList {
 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
 | 
						allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
 | 
				
			||||||
@@ -502,108 +170,3 @@ func validateIngressBackend(backend *extensions.IngressBackend, fldPath *field.P
 | 
				
			|||||||
	allErrs = append(allErrs, apivalidation.ValidatePortNumOrName(backend.ServicePort, fldPath.Child("servicePort"))...)
 | 
						allErrs = append(allErrs, apivalidation.ValidatePortNumOrName(backend.ServicePort, fldPath.Child("servicePort"))...)
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateReplicaSetName can be used to check whether the given ReplicaSet
 | 
					 | 
				
			||||||
// name is valid.
 | 
					 | 
				
			||||||
// Prefix indicates this name will be used as part of generation, in which case
 | 
					 | 
				
			||||||
// trailing dashes are allowed.
 | 
					 | 
				
			||||||
var ValidateReplicaSetName = apimachineryvalidation.NameIsDNSSubdomain
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateReplicaSet tests if required fields in the ReplicaSet are set.
 | 
					 | 
				
			||||||
func ValidateReplicaSet(rs *extensions.ReplicaSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := apivalidation.ValidateObjectMeta(&rs.ObjectMeta, true, ValidateReplicaSetName, field.NewPath("metadata"))
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateReplicaSetSpec(&rs.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateReplicaSetUpdate tests if required fields in the ReplicaSet are set.
 | 
					 | 
				
			||||||
func ValidateReplicaSetUpdate(rs, oldRs *extensions.ReplicaSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&rs.ObjectMeta, &oldRs.ObjectMeta, field.NewPath("metadata"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateReplicaSetSpec(&rs.Spec, field.NewPath("spec"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateReplicaSetStatusUpdate tests if required fields in the ReplicaSet are set.
 | 
					 | 
				
			||||||
func ValidateReplicaSetStatusUpdate(rs, oldRs *extensions.ReplicaSet) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&rs.ObjectMeta, &oldRs.ObjectMeta, field.NewPath("metadata"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, ValidateReplicaSetStatus(rs.Status, field.NewPath("status"))...)
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ValidateReplicaSetStatus(status extensions.ReplicaSetStatus, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Replicas), fldPath.Child("replicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.FullyLabeledReplicas), fldPath.Child("fullyLabeledReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ReadyReplicas), fldPath.Child("readyReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.AvailableReplicas), fldPath.Child("availableReplicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ObservedGeneration), fldPath.Child("observedGeneration"))...)
 | 
					 | 
				
			||||||
	msg := "cannot be greater than status.replicas"
 | 
					 | 
				
			||||||
	if status.FullyLabeledReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("fullyLabeledReplicas"), status.FullyLabeledReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.ReadyReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("readyReplicas"), status.ReadyReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.AvailableReplicas > status.Replicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, msg))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if status.AvailableReplicas > status.ReadyReplicas {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("availableReplicas"), status.AvailableReplicas, "cannot be greater than readyReplicas"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ValidateReplicaSetSpec tests if required fields in the ReplicaSet spec are set.
 | 
					 | 
				
			||||||
func ValidateReplicaSetSpec(spec *extensions.ReplicaSetSpec, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...)
 | 
					 | 
				
			||||||
	allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if spec.Selector == nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
 | 
					 | 
				
			||||||
		if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is invalid for deployment"))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	selector, err := metav1.LabelSelectorAsSelector(spec.Selector)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "invalid label selector"))
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Validates the given template and ensures that it is in accordance with the desired selector and replicas.
 | 
					 | 
				
			||||||
func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selector labels.Selector, replicas int32, fldPath *field.Path) field.ErrorList {
 | 
					 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
					 | 
				
			||||||
	if template == nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Required(fldPath, ""))
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if !selector.Empty() {
 | 
					 | 
				
			||||||
			// Verify that the ReplicaSet selector matches the labels in template.
 | 
					 | 
				
			||||||
			labels := labels.Set(template.Labels)
 | 
					 | 
				
			||||||
			if !selector.Matches(labels) {
 | 
					 | 
				
			||||||
				allErrs = append(allErrs, field.Invalid(fldPath.Child("metadata", "labels"), template.Labels, "`selector` does not match template `labels`"))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(template, fldPath)...)
 | 
					 | 
				
			||||||
		if replicas > 1 {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(template.Spec.Volumes, fldPath.Child("spec", "volumes"))...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
 | 
					 | 
				
			||||||
		if template.Spec.RestartPolicy != api.RestartPolicyAlways {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.NotSupported(fldPath.Child("spec", "restartPolicy"), template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)}))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if template.Spec.ActiveDeadlineSeconds != nil {
 | 
					 | 
				
			||||||
			allErrs = append(allErrs, field.Invalid(fldPath.Child("spec", "activeDeadlineSeconds"), template.Spec.ActiveDeadlineSeconds, "must not be specified"))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return allErrs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user