2015-08-06 14:14:28 +00:00
/ *
Copyright 2015 The Kubernetes Authors All rights reserved .
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package validation
import (
2015-03-31 21:36:25 +00:00
"fmt"
2015-09-23 03:20:13 +00:00
"net"
"regexp"
2015-08-25 19:07:03 +00:00
"strconv"
2015-09-23 03:20:13 +00:00
"strings"
2015-08-25 19:07:03 +00:00
2015-08-06 14:14:28 +00:00
"k8s.io/kubernetes/pkg/api"
apivalidation "k8s.io/kubernetes/pkg/api/validation"
2015-10-09 22:04:41 +00:00
"k8s.io/kubernetes/pkg/apis/extensions"
2015-08-27 17:17:41 +00:00
"k8s.io/kubernetes/pkg/labels"
2015-11-10 06:28:45 +00:00
"k8s.io/kubernetes/pkg/util/intstr"
2015-09-09 17:45:01 +00:00
"k8s.io/kubernetes/pkg/util/sets"
2015-09-10 22:48:28 +00:00
"k8s.io/kubernetes/pkg/util/validation"
2015-11-06 23:30:52 +00:00
"k8s.io/kubernetes/pkg/util/validation/field"
2015-08-06 14:14:28 +00:00
)
// ValidateHorizontalPodAutoscaler can be used to check whether the given autoscaler name is valid.
// Prefix indicates this name will be used as part of generation, in which case trailing dashes are allowed.
func ValidateHorizontalPodAutoscalerName ( name string , prefix bool ) ( bool , string ) {
// TODO: finally move it to pkg/api/validation and use nameIsDNSSubdomain function
return apivalidation . ValidateReplicationControllerName ( name , prefix )
}
2015-11-06 23:30:52 +00:00
func validateHorizontalPodAutoscalerSpec ( autoscaler extensions . HorizontalPodAutoscalerSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-10-13 15:24:23 +00:00
if autoscaler . MinReplicas != nil && * autoscaler . MinReplicas < 1 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "minReplicas" ) , * autoscaler . MinReplicas , "must be greater than 0" ) )
2015-08-06 14:14:28 +00:00
}
2015-10-13 15:24:23 +00:00
if autoscaler . MaxReplicas < 1 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "maxReplicas" ) , autoscaler . MaxReplicas , "must be greater than 0" ) )
2015-08-06 14:14:28 +00:00
}
2015-10-13 15:24:23 +00:00
if autoscaler . MinReplicas != nil && autoscaler . MaxReplicas < * autoscaler . MinReplicas {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "maxReplicas" ) , autoscaler . MaxReplicas , "must be greater than or equal to `minReplicas`" ) )
2015-08-06 14:14:28 +00:00
}
2015-10-13 15:24:23 +00:00
if autoscaler . CPUUtilization != nil && autoscaler . CPUUtilization . TargetPercentage < 1 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "cpuUtilization" , "targetPercentage" ) , autoscaler . CPUUtilization . TargetPercentage , "must be greater than 0" ) )
2015-08-06 14:14:28 +00:00
}
2015-11-04 21:52:14 +00:00
if refErrs := ValidateSubresourceReference ( autoscaler . ScaleRef , fldPath . Child ( "scaleRef" ) ) ; len ( refErrs ) > 0 {
2015-11-06 05:42:59 +00:00
allErrs = append ( allErrs , refErrs ... )
2015-11-03 06:55:32 +00:00
} else if autoscaler . ScaleRef . Subresource != "scale" {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . NotSupported ( fldPath . Child ( "scaleRef" , "subresource" ) , autoscaler . ScaleRef . Subresource , [ ] string { "scale" } ) )
2015-11-03 06:55:32 +00:00
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateSubresourceReference ( ref extensions . SubresourceReference , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-03 06:55:32 +00:00
if len ( ref . Kind ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "kind" ) , "" ) )
2015-11-03 06:55:32 +00:00
} else if ok , msg := apivalidation . IsValidPathSegmentName ( ref . Kind ) ; ! ok {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "kind" ) , ref . Kind , msg ) )
2015-11-03 06:55:32 +00:00
}
if len ( ref . Name ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "name" ) , "" ) )
2015-11-03 06:55:32 +00:00
} else if ok , msg := apivalidation . IsValidPathSegmentName ( ref . Name ) ; ! ok {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "name" ) , ref . Name , msg ) )
2015-11-03 06:55:32 +00:00
}
if len ( ref . Subresource ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "subresource" ) , "" ) )
2015-11-03 06:55:32 +00:00
} else if ok , msg := apivalidation . IsValidPathSegmentName ( ref . Subresource ) ; ! ok {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "subresource" ) , ref . Subresource , msg ) )
2015-11-03 06:55:32 +00:00
}
2015-08-06 14:14:28 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateHorizontalPodAutoscaler ( autoscaler * extensions . HorizontalPodAutoscaler ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMeta ( & autoscaler . ObjectMeta , true , ValidateHorizontalPodAutoscalerName , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , validateHorizontalPodAutoscalerSpec ( autoscaler . Spec , field . NewPath ( "spec" ) ) ... )
2015-08-06 14:14:28 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateHorizontalPodAutoscalerUpdate ( newAutoscaler , oldAutoscaler * extensions . HorizontalPodAutoscaler ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & newAutoscaler . ObjectMeta , & oldAutoscaler . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , validateHorizontalPodAutoscalerSpec ( newAutoscaler . Spec , field . NewPath ( "spec" ) ) ... )
2015-08-06 14:14:28 +00:00
return allErrs
}
2015-08-15 05:10:15 +00:00
2015-11-06 23:30:52 +00:00
func ValidateHorizontalPodAutoscalerStatusUpdate ( controller , oldController * extensions . HorizontalPodAutoscaler ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & controller . ObjectMeta , & oldController . ObjectMeta , field . NewPath ( "metadata" ) )
2015-09-25 17:57:05 +00:00
status := controller . Status
2015-11-06 23:30:52 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . CurrentReplicas ) , field . NewPath ( "status" , "currentReplicas" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . DesiredReplicas ) , field . NewPath ( "status" , "desiredReplicasa" ) ) ... )
2015-09-25 17:57:05 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateThirdPartyResourceUpdate ( update , old * extensions . ThirdPartyResource ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , apivalidation . ValidateObjectMetaUpdate ( & update . ObjectMeta , & old . ObjectMeta , field . NewPath ( "metadata" ) ) ... )
2015-11-13 05:00:19 +00:00
allErrs = append ( allErrs , ValidateThirdPartyResource ( update ) ... )
return allErrs
}
func ValidateThirdPartyResourceName ( name string , prefix bool ) ( bool , string ) {
return apivalidation . NameIsDNSSubdomain ( name , prefix )
2015-08-15 05:10:15 +00:00
}
2015-11-06 23:30:52 +00:00
func ValidateThirdPartyResource ( obj * extensions . ThirdPartyResource ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , apivalidation . ValidateObjectMeta ( & obj . ObjectMeta , true , ValidateThirdPartyResourceName , field . NewPath ( "metadata" ) ) ... )
2015-11-13 05:00:19 +00:00
2015-09-09 17:45:01 +00:00
versions := sets . String { }
2015-08-15 05:10:15 +00:00
for ix := range obj . Versions {
version := & obj . Versions [ ix ]
if len ( version . Name ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( field . NewPath ( "versions" ) . Index ( ix ) . Child ( "name" ) , version , "must not be empty" ) )
2015-08-15 05:10:15 +00:00
}
if versions . Has ( version . Name ) {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Duplicate ( field . NewPath ( "versions" ) . Index ( ix ) . Child ( "name" ) , version ) )
2015-08-15 05:10:15 +00:00
}
versions . Insert ( version . Name )
}
return allErrs
}
2015-08-27 17:17:41 +00:00
2015-09-08 23:58:25 +00:00
// ValidateDaemonSet tests if required fields in the DaemonSet are set.
2015-11-06 23:30:52 +00:00
func ValidateDaemonSet ( controller * extensions . DaemonSet ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMeta ( & controller . ObjectMeta , true , ValidateDaemonSetName , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateDaemonSetSpec ( & controller . Spec , field . NewPath ( "spec" ) ) ... )
2015-08-27 17:17:41 +00:00
return allErrs
}
2015-09-08 23:58:25 +00:00
// ValidateDaemonSetUpdate tests if required fields in the DaemonSet are set.
2015-11-06 23:30:52 +00:00
func ValidateDaemonSetUpdate ( controller , oldController * extensions . DaemonSet ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & controller . ObjectMeta , & oldController . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateDaemonSetSpec ( & controller . Spec , field . NewPath ( "spec" ) ) ... )
allErrs = append ( allErrs , ValidateDaemonSetTemplateUpdate ( controller . Spec . Template , oldController . Spec . Template , field . NewPath ( "spec" , "template" ) ) ... )
2015-08-27 17:17:41 +00:00
return allErrs
}
2015-09-25 02:51:09 +00:00
// validateDaemonSetStatus validates a DaemonSetStatus
2015-11-06 23:30:52 +00:00
func validateDaemonSetStatus ( status * extensions . DaemonSetStatus , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . CurrentNumberScheduled ) , fldPath . Child ( "currentNumberScheduled" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . NumberMisscheduled ) , fldPath . Child ( "numberMisscheduled" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . DesiredNumberScheduled ) , fldPath . Child ( "desiredNumberScheduled" ) ) ... )
2015-09-25 02:51:09 +00:00
return allErrs
}
// ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section
2015-11-06 23:30:52 +00:00
func ValidateDaemonSetStatusUpdate ( controller , oldController * extensions . DaemonSet ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & controller . ObjectMeta , & oldController . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , validateDaemonSetStatus ( & controller . Status , field . NewPath ( "status" ) ) ... )
2015-09-25 02:51:09 +00:00
return allErrs
}
2015-09-08 23:58:25 +00:00
// ValidateDaemonSetTemplateUpdate tests that certain fields in the daemon set's pod template are not updated.
2015-11-06 23:30:52 +00:00
func ValidateDaemonSetTemplateUpdate ( podTemplate , oldPodTemplate * api . PodTemplateSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-27 17:17:41 +00:00
podSpec := podTemplate . Spec
// podTemplate.Spec is not a pointer, so we can modify NodeSelector and NodeName directly.
podSpec . NodeSelector = oldPodTemplate . Spec . NodeSelector
podSpec . NodeName = oldPodTemplate . Spec . NodeName
// In particular, we do not allow updates to container images at this point.
if ! api . Semantic . DeepEqual ( oldPodTemplate . Spec , podSpec ) {
// TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Forbidden ( fldPath . Child ( "spec" ) , "daemonSet updates may not change fields other than `nodeSelector`" ) )
2015-08-27 17:17:41 +00:00
}
return allErrs
}
2015-09-08 23:58:25 +00:00
// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set.
2015-11-06 23:30:52 +00:00
func ValidateDaemonSetSpec ( spec * extensions . DaemonSetSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-27 17:17:41 +00:00
2015-12-01 09:24:21 +00:00
allErrs = append ( allErrs , ValidateLabelSelector ( spec . Selector , fldPath . Child ( "selector" ) ) ... )
2015-08-27 17:17:41 +00:00
if spec . Template == nil {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "template" ) , "" ) )
2015-10-26 06:11:09 +00:00
return allErrs
}
2015-12-01 09:24:21 +00:00
selector , err := extensions . LabelSelectorAsSelector ( spec . Selector )
2015-10-26 06:11:09 +00:00
if err == nil && ! selector . Matches ( labels . Set ( spec . Template . Labels ) ) {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "template" , "metadata" , "labels" ) , spec . Template . Labels , "`selector` does not match template `labels`" ) )
2015-08-27 17:17:41 +00:00
}
2015-10-26 06:11:09 +00:00
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePodTemplateSpec ( spec . Template , fldPath . Child ( "template" ) ) ... )
2015-10-26 06:11:09 +00:00
// Daemons typically run on more than one node, so mark Read-Write persistent disks as invalid.
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidateReadOnlyPersistentDisks ( spec . Template . Spec . Volumes , fldPath . Child ( "template" , "spec" , "volumes" ) ) ... )
2015-10-26 06:11:09 +00:00
// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
if spec . Template . Spec . RestartPolicy != api . RestartPolicyAlways {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . NotSupported ( fldPath . Child ( "template" , "spec" , "restartPolicy" ) , spec . Template . Spec . RestartPolicy , [ ] string { string ( api . RestartPolicyAlways ) } ) )
2015-10-26 06:11:09 +00:00
}
2015-08-27 17:17:41 +00:00
return allErrs
}
2015-09-08 23:58:25 +00:00
// ValidateDaemonSetName can be used to check whether the given daemon set name is valid.
2015-08-27 17:17:41 +00:00
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
2015-09-08 23:58:25 +00:00
func ValidateDaemonSetName ( name string , prefix bool ) ( bool , string ) {
2015-08-27 17:17:41 +00:00
return apivalidation . NameIsDNSSubdomain ( name , prefix )
}
2015-08-25 19:07:03 +00:00
// Validates that the given name can be used as a deployment name.
func ValidateDeploymentName ( name string , prefix bool ) ( bool , string ) {
return apivalidation . NameIsDNSSubdomain ( name , prefix )
}
2015-11-06 23:30:52 +00:00
func ValidatePositiveIntOrPercent ( intOrPercent intstr . IntOrString , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-10 06:28:45 +00:00
if intOrPercent . Type == intstr . String {
2015-09-10 22:48:28 +00:00
if ! validation . IsValidPercent ( intOrPercent . StrVal ) {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath , intOrPercent , "must be an integer or percentage (e.g '5%')" ) )
2015-08-25 19:07:03 +00:00
}
2015-11-10 06:28:45 +00:00
} else if intOrPercent . Type == intstr . Int {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( intOrPercent . IntValue ( ) ) , fldPath ) ... )
2015-08-25 19:07:03 +00:00
}
return allErrs
}
2015-11-10 06:28:45 +00:00
func getPercentValue ( intOrStringValue intstr . IntOrString ) ( int , bool ) {
if intOrStringValue . Type != intstr . String || ! validation . IsValidPercent ( intOrStringValue . StrVal ) {
2015-08-25 19:07:03 +00:00
return 0 , false
}
value , _ := strconv . Atoi ( intOrStringValue . StrVal [ : len ( intOrStringValue . StrVal ) - 1 ] )
return value , true
}
2015-11-10 06:28:45 +00:00
func getIntOrPercentValue ( intOrStringValue intstr . IntOrString ) int {
2015-08-25 19:07:03 +00:00
value , isPercent := getPercentValue ( intOrStringValue )
if isPercent {
return value
}
2015-11-18 18:15:16 +00:00
return intOrStringValue . IntValue ( )
2015-08-25 19:07:03 +00:00
}
2015-11-06 23:30:52 +00:00
func IsNotMoreThan100Percent ( intOrStringValue intstr . IntOrString , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-25 19:07:03 +00:00
value , isPercent := getPercentValue ( intOrStringValue )
if ! isPercent || value <= 100 {
return nil
}
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath , intOrStringValue , "must not be greater than 100%" ) )
2015-08-25 19:07:03 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateRollingUpdateDeployment ( rollingUpdate * extensions . RollingUpdateDeployment , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , ValidatePositiveIntOrPercent ( rollingUpdate . MaxUnavailable , fldPath . Child ( "maxUnavailable" ) ) ... )
allErrs = append ( allErrs , ValidatePositiveIntOrPercent ( rollingUpdate . MaxSurge , fldPath . Child ( "maxSurge" ) ) ... )
2015-08-25 19:07:03 +00:00
if getIntOrPercentValue ( rollingUpdate . MaxUnavailable ) == 0 && getIntOrPercentValue ( rollingUpdate . MaxSurge ) == 0 {
// Both MaxSurge and MaxUnavailable cannot be zero.
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "maxUnavailable" ) , rollingUpdate . MaxUnavailable , "may not be 0 when `maxSurge` is 0" ) )
2015-08-25 19:07:03 +00:00
}
// Validate that MaxUnavailable is not more than 100%.
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , IsNotMoreThan100Percent ( rollingUpdate . MaxUnavailable , fldPath . Child ( "maxUnavailable" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( rollingUpdate . MinReadySeconds ) , fldPath . Child ( "minReadySeconds" ) ) ... )
2015-08-25 19:07:03 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateDeploymentStrategy ( strategy * extensions . DeploymentStrategy , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-25 19:07:03 +00:00
if strategy . RollingUpdate == nil {
return allErrs
}
switch strategy . Type {
2015-10-09 22:49:10 +00:00
case extensions . RecreateDeploymentStrategyType :
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Forbidden ( fldPath . Child ( "rollingUpdate" ) , "may not be specified when strategy `type` is '" + string ( extensions . RecreateDeploymentStrategyType + "'" ) ) )
2015-10-09 22:49:10 +00:00
case extensions . RollingUpdateDeploymentStrategyType :
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , ValidateRollingUpdateDeployment ( strategy . RollingUpdate , fldPath . Child ( "rollingUpdate" ) ) ... )
2015-08-25 19:07:03 +00:00
}
return allErrs
}
// Validates given deployment spec.
2015-11-06 23:30:52 +00:00
func ValidateDeploymentSpec ( spec * extensions . DeploymentSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidateNonEmptySelector ( spec . Selector , fldPath . Child ( "selector" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( spec . Replicas ) , fldPath . Child ( "replicas" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePodTemplateSpecForRC ( & spec . Template , spec . Selector , spec . Replicas , fldPath . Child ( "template" ) ) ... )
allErrs = append ( allErrs , ValidateDeploymentStrategy ( & spec . Strategy , fldPath . Child ( "strategy" ) ) ... )
2015-11-13 01:07:21 +00:00
// empty string is a valid UniqueLabelKey
if len ( spec . UniqueLabelKey ) > 0 {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidateLabelName ( spec . UniqueLabelKey , fldPath . Child ( "uniqueLabel" ) ) ... )
2015-11-13 01:07:21 +00:00
}
2015-08-25 19:07:03 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
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" ) ) ... )
2015-08-25 19:07:03 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
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" ) ) ... )
2015-08-25 19:07:03 +00:00
return allErrs
}
2015-08-20 05:08:26 +00:00
2015-11-06 23:30:52 +00:00
func ValidateThirdPartyResourceDataUpdate ( update , old * extensions . ThirdPartyResourceData ) field . ErrorList {
2015-08-20 05:08:26 +00:00
return ValidateThirdPartyResourceData ( update )
}
2015-11-06 23:30:52 +00:00
func ValidateThirdPartyResourceData ( obj * extensions . ThirdPartyResourceData ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-20 05:08:26 +00:00
if len ( obj . Name ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( field . NewPath ( "name" ) , "" ) )
2015-08-20 05:08:26 +00:00
}
return allErrs
}
2015-08-18 14:39:49 +00:00
2015-11-06 23:30:52 +00:00
func ValidateJob ( job * extensions . Job ) field . ErrorList {
2015-08-18 14:39:49 +00:00
// Jobs and rcs have the same name validation
2015-11-06 23:30:52 +00:00
allErrs := apivalidation . ValidateObjectMeta ( & job . ObjectMeta , true , apivalidation . ValidateReplicationControllerName , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateJobSpec ( & job . Spec , field . NewPath ( "spec" ) ) ... )
2015-08-18 14:39:49 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateJobSpec ( spec * extensions . JobSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-08-18 14:39:49 +00:00
2015-10-12 03:26:17 +00:00
if spec . Parallelism != nil {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( * spec . Parallelism ) , fldPath . Child ( "parallelism" ) ) ... )
2015-08-18 14:39:49 +00:00
}
2015-10-12 03:26:17 +00:00
if spec . Completions != nil {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( * spec . Completions ) , fldPath . Child ( "completions" ) ) ... )
2015-08-18 14:39:49 +00:00
}
2015-11-26 15:54:04 +00:00
if spec . ActiveDeadlineSeconds != nil {
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( * spec . ActiveDeadlineSeconds ) , fldPath . Child ( "activeDeadlineSeconds" ) ) ... )
}
2015-10-14 18:03:59 +00:00
if spec . Selector == nil {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "selector" ) , "" ) )
2015-10-14 18:03:59 +00:00
} else {
2015-12-01 09:24:21 +00:00
allErrs = append ( allErrs , ValidateLabelSelector ( spec . Selector , fldPath . Child ( "selector" ) ) ... )
2015-08-18 14:39:49 +00:00
}
2015-12-01 09:24:21 +00:00
if selector , err := extensions . LabelSelectorAsSelector ( spec . Selector ) ; err == nil {
2015-10-14 18:03:59 +00:00
labels := labels . Set ( spec . Template . Labels )
if ! selector . Matches ( labels ) {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "template" , "metadata" , "labels" ) , spec . Template . Labels , "`selector` does not match template `labels`" ) )
2015-10-14 18:03:59 +00:00
}
2015-09-25 19:07:06 +00:00
}
2015-10-14 18:03:59 +00:00
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePodTemplateSpec ( & spec . Template , fldPath . Child ( "template" ) ) ... )
2015-09-25 19:07:06 +00:00
if spec . Template . Spec . RestartPolicy != api . RestartPolicyOnFailure &&
spec . Template . Spec . RestartPolicy != api . RestartPolicyNever {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . NotSupported ( fldPath . Child ( "template" , "spec" , "restartPolicy" ) ,
2015-09-25 19:07:06 +00:00
spec . Template . Spec . RestartPolicy , [ ] string { string ( api . RestartPolicyOnFailure ) , string ( api . RestartPolicyNever ) } ) )
2015-08-18 14:39:49 +00:00
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateJobStatus ( status * extensions . JobStatus , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . Active ) , fldPath . Child ( "active" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . Succeeded ) , fldPath . Child ( "succeeded" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidatePositiveField ( int64 ( status . Failed ) , fldPath . Child ( "failed" ) ) ... )
2015-09-22 08:05:54 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateJobUpdate ( job , oldJob * extensions . Job ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & oldJob . ObjectMeta , & job . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateJobSpecUpdate ( job . Spec , oldJob . Spec , field . NewPath ( "spec" ) ) ... )
2015-09-17 22:58:04 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateJobUpdateStatus ( job , oldJob * extensions . Job ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & oldJob . ObjectMeta , & job . ObjectMeta , field . NewPath ( "metadata" ) )
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , ValidateJobStatusUpdate ( job . Status , oldJob . Status ) ... )
2015-09-22 08:05:54 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateJobSpecUpdate ( spec , oldSpec extensions . JobSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , ValidateJobSpec ( & spec , fldPath ) ... )
allErrs = append ( allErrs , apivalidation . ValidateImmutableField ( spec . Completions , oldSpec . Completions , fldPath . Child ( "completions" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidateImmutableField ( spec . Selector , oldSpec . Selector , fldPath . Child ( "selector" ) ) ... )
allErrs = append ( allErrs , apivalidation . ValidateImmutableField ( spec . Template , oldSpec . Template , fldPath . Child ( "template" ) ) ... )
2015-08-18 14:39:49 +00:00
return allErrs
}
2015-09-22 08:05:54 +00:00
2015-11-06 23:30:52 +00:00
func ValidateJobStatusUpdate ( status , oldStatus extensions . JobStatus ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , ValidateJobStatus ( & status , field . NewPath ( "status" ) ) ... )
2015-09-22 08:05:54 +00:00
return allErrs
}
2015-09-22 18:26:36 +00:00
2015-09-23 03:20:13 +00:00
// ValidateIngress tests if required fields in the Ingress are set.
2015-11-06 23:30:52 +00:00
func ValidateIngress ( ingress * extensions . Ingress ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMeta ( & ingress . ObjectMeta , true , ValidateIngressName , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateIngressSpec ( & ingress . Spec , field . NewPath ( "spec" ) ) ... )
2015-09-23 03:20:13 +00:00
return allErrs
}
2015-09-22 18:26:36 +00:00
// ValidateIngressName validates that the given name can be used as an Ingress name.
func ValidateIngressName ( name string , prefix bool ) ( bool , string ) {
return apivalidation . NameIsDNSSubdomain ( name , prefix )
}
// ValidateIngressSpec tests if required fields in the IngressSpec are set.
2015-11-06 23:30:52 +00:00
func ValidateIngressSpec ( spec * extensions . IngressSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-09-23 03:20:13 +00:00
// TODO: Is a default backend mandatory?
if spec . Backend != nil {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , validateIngressBackend ( spec . Backend , fldPath . Child ( "backend" ) ) ... )
2015-09-23 03:20:13 +00:00
} else if len ( spec . Rules ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath , spec . Rules , "either `backend` or `rules` must be specified" ) )
2015-09-23 03:20:13 +00:00
}
if len ( spec . Rules ) > 0 {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , validateIngressRules ( spec . Rules , fldPath . Child ( "rules" ) ) ... )
2015-09-23 03:20:13 +00:00
}
2015-09-22 18:26:36 +00:00
return allErrs
}
2015-09-23 03:20:13 +00:00
// ValidateIngressUpdate tests if required fields in the Ingress are set.
2015-11-06 23:30:52 +00:00
func ValidateIngressUpdate ( ingress , oldIngress * extensions . Ingress ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & ingress . ObjectMeta , & oldIngress . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , ValidateIngressSpec ( & ingress . Spec , field . NewPath ( "spec" ) ) ... )
2015-09-22 18:26:36 +00:00
return allErrs
}
2015-10-12 19:09:20 +00:00
// ValidateIngressStatusUpdate tests if required fields in the Ingress are set when updating status.
2015-11-06 23:30:52 +00:00
func ValidateIngressStatusUpdate ( ingress , oldIngress * extensions . Ingress ) field . ErrorList {
allErrs := apivalidation . ValidateObjectMetaUpdate ( & ingress . ObjectMeta , & oldIngress . ObjectMeta , field . NewPath ( "metadata" ) )
allErrs = append ( allErrs , apivalidation . ValidateLoadBalancerStatus ( & ingress . Status . LoadBalancer , field . NewPath ( "status" , "loadBalancer" ) ) ... )
2015-10-12 19:09:20 +00:00
return allErrs
}
2015-11-06 23:30:52 +00:00
func validateIngressRules ( IngressRules [ ] extensions . IngressRule , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-09-23 03:20:13 +00:00
if len ( IngressRules ) == 0 {
2015-11-14 20:26:04 +00:00
return append ( allErrs , field . Required ( fldPath , "" ) )
2015-09-23 03:20:13 +00:00
}
2015-11-04 21:52:14 +00:00
for i , ih := range IngressRules {
2015-09-23 03:20:13 +00:00
if len ( ih . Host ) > 0 {
// TODO: Ports and ips are allowed in the host part of a url
// according to RFC 3986, consider allowing them.
if valid , errMsg := apivalidation . NameIsDNSSubdomain ( ih . Host , false ) ; ! valid {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Index ( i ) . Child ( "host" ) , ih . Host , errMsg ) )
2015-09-23 03:20:13 +00:00
}
if isIP := ( net . ParseIP ( ih . Host ) != nil ) ; isIP {
2015-11-14 16:44:50 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Index ( i ) . Child ( "host" ) , ih . Host , "must be a DNS name, not an IP address" ) )
2015-09-23 03:20:13 +00:00
}
}
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , validateIngressRuleValue ( & ih . IngressRuleValue , fldPath . Index ( 0 ) ) ... )
2015-09-23 03:20:13 +00:00
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func validateIngressRuleValue ( ingressRule * extensions . IngressRuleValue , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-09-23 03:20:13 +00:00
if ingressRule . HTTP != nil {
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , validateHTTPIngressRuleValue ( ingressRule . HTTP , fldPath . Child ( "http" ) ) ... )
2015-09-23 03:20:13 +00:00
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func validateHTTPIngressRuleValue ( httpIngressRuleValue * extensions . HTTPIngressRuleValue , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-09-23 03:20:13 +00:00
if len ( httpIngressRuleValue . Paths ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "paths" ) , "" ) )
2015-09-23 03:20:13 +00:00
}
2015-11-04 21:52:14 +00:00
for i , rule := range httpIngressRuleValue . Paths {
2015-09-23 03:20:13 +00:00
if len ( rule . Path ) > 0 {
if ! strings . HasPrefix ( rule . Path , "/" ) {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "paths" ) . Index ( i ) . Child ( "path" ) , rule . Path , "must be an absolute path" ) )
2015-09-23 03:20:13 +00:00
}
// TODO: More draconian path regex validation.
// Path must be a valid regex. This is the basic requirement.
// In addition to this any characters not allowed in a path per
// RFC 3986 section-3.3 cannot appear as a literal in the regex.
// Consider the example: http://host/valid?#bar, everything after
// the last '/' is a valid regex that matches valid#bar, which
// isn't a valid path, because the path terminates at the first ?
// or #. A more sophisticated form of validation would detect that
// the user is confusing url regexes with path regexes.
_ , err := regexp . CompilePOSIX ( rule . Path )
if err != nil {
2015-11-14 16:44:50 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "paths" ) . Index ( i ) . Child ( "path" ) , rule . Path , "must be a valid regex" ) )
2015-09-23 03:20:13 +00:00
}
}
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , validateIngressBackend ( & rule . Backend , fldPath . Child ( "backend" ) ) ... )
2015-09-23 03:20:13 +00:00
}
return allErrs
}
// validateIngressBackend tests if a given backend is valid.
2015-11-06 23:30:52 +00:00
func validateIngressBackend ( backend * extensions . IngressBackend , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-09-23 03:20:13 +00:00
// All backends must reference a single local service by name, and a single service port by name or number.
if len ( backend . ServiceName ) == 0 {
2015-11-14 20:26:04 +00:00
return append ( allErrs , field . Required ( fldPath . Child ( "serviceName" ) , "" ) )
2015-09-23 03:20:13 +00:00
} else if ok , errMsg := apivalidation . ValidateServiceName ( backend . ServiceName , false ) ; ! ok {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "serviceName" ) , backend . ServiceName , errMsg ) )
2015-09-23 03:20:13 +00:00
}
2015-11-10 06:28:45 +00:00
if backend . ServicePort . Type == intstr . String {
2015-11-03 21:17:51 +00:00
if ! validation . IsDNS1123Label ( backend . ServicePort . StrVal ) {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "servicePort" ) , backend . ServicePort . StrVal , apivalidation . DNS1123LabelErrorMsg ) )
2015-09-23 03:20:13 +00:00
}
2015-11-03 21:17:51 +00:00
if ! validation . IsValidPortName ( backend . ServicePort . StrVal ) {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "servicePort" ) , backend . ServicePort . StrVal , apivalidation . PortNameErrorMsg ) )
2015-09-23 03:20:13 +00:00
}
2015-11-18 18:15:16 +00:00
} else if ! validation . IsValidPortNum ( backend . ServicePort . IntValue ( ) ) {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "servicePort" ) , backend . ServicePort , apivalidation . PortRangeErrorMsg ) )
2015-09-23 03:20:13 +00:00
}
2015-09-22 18:26:36 +00:00
return allErrs
}
2015-10-05 20:22:01 +00:00
2015-11-06 23:30:52 +00:00
func validateClusterAutoscalerSpec ( spec extensions . ClusterAutoscalerSpec , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-10-05 20:22:01 +00:00
if spec . MinNodes < 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "minNodes" ) , spec . MinNodes , "must be greater than or equal to 0" ) )
2015-10-05 20:22:01 +00:00
}
if spec . MaxNodes < spec . MinNodes {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "maxNodes" ) , spec . MaxNodes , "must be greater than or equal to `minNodes`" ) )
2015-10-05 20:22:01 +00:00
}
if len ( spec . TargetUtilization ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "targetUtilization" ) , "" ) )
2015-10-05 20:22:01 +00:00
}
for _ , target := range spec . TargetUtilization {
if len ( target . Resource ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "targetUtilization" , "resource" ) , "" ) )
2015-10-05 20:22:01 +00:00
}
if target . Value <= 0 {
2015-11-10 20:59:41 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "targetUtilization" , "value" ) , target . Value , "must be greater than 0" ) )
2015-10-05 20:22:01 +00:00
}
if target . Value > 1 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "targetUtilization" , "value" ) , target . Value , "must be less than or equal to 1" ) )
2015-10-05 20:22:01 +00:00
}
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateClusterAutoscaler ( autoscaler * extensions . ClusterAutoscaler ) field . ErrorList {
allErrs := field . ErrorList { }
2015-10-05 20:22:01 +00:00
if autoscaler . Name != "ClusterAutoscaler" {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( field . NewPath ( "metadata" , "name" ) , autoscaler . Name , "must be 'ClusterAutoscaler'" ) )
2015-10-05 20:22:01 +00:00
}
if autoscaler . Namespace != api . NamespaceDefault {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( field . NewPath ( "metadata" , "namespace" ) , autoscaler . Namespace , "must be 'default'" ) )
2015-10-05 20:22:01 +00:00
}
2015-11-06 23:30:52 +00:00
allErrs = append ( allErrs , validateClusterAutoscalerSpec ( autoscaler . Spec , field . NewPath ( "spec" ) ) ... )
2015-10-05 20:22:01 +00:00
return allErrs
}
2015-10-14 18:03:59 +00:00
2015-11-06 23:30:52 +00:00
func ValidateLabelSelector ( ps * extensions . LabelSelector , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-10-14 18:03:59 +00:00
if ps == nil {
return allErrs
}
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidateLabels ( ps . MatchLabels , fldPath . Child ( "matchLabels" ) ) ... )
2015-10-14 18:03:59 +00:00
for i , expr := range ps . MatchExpressions {
2015-12-01 09:24:21 +00:00
allErrs = append ( allErrs , ValidateLabelSelectorRequirement ( expr , fldPath . Child ( "matchExpressions" ) . Index ( i ) ) ... )
2015-10-14 18:03:59 +00:00
}
return allErrs
}
2015-11-06 23:30:52 +00:00
func ValidateLabelSelectorRequirement ( sr extensions . LabelSelectorRequirement , fldPath * field . Path ) field . ErrorList {
allErrs := field . ErrorList { }
2015-10-14 18:03:59 +00:00
switch sr . Operator {
2015-12-01 09:24:21 +00:00
case extensions . LabelSelectorOpIn , extensions . LabelSelectorOpNotIn :
2015-10-14 18:03:59 +00:00
if len ( sr . Values ) == 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Required ( fldPath . Child ( "values" ) , "must be specified when `operator` is 'In' or 'NotIn'" ) )
2015-10-14 18:03:59 +00:00
}
2015-12-01 09:24:21 +00:00
case extensions . LabelSelectorOpExists , extensions . LabelSelectorOpDoesNotExist :
2015-10-14 18:03:59 +00:00
if len ( sr . Values ) > 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Forbidden ( fldPath . Child ( "values" ) , "may not be specified when `operator` is 'Exists' or 'DoesNotExist'" ) )
2015-10-14 18:03:59 +00:00
}
default :
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( fldPath . Child ( "operator" ) , sr . Operator , "not a valid selector operator" ) )
2015-10-14 18:03:59 +00:00
}
2015-11-04 21:52:14 +00:00
allErrs = append ( allErrs , apivalidation . ValidateLabelName ( sr . Key , fldPath . Child ( "key" ) ) ... )
2015-10-14 18:03:59 +00:00
return allErrs
}
2015-11-02 18:50:43 +00:00
2015-11-06 23:30:52 +00:00
func ValidateScale ( scale * extensions . Scale ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , apivalidation . ValidateObjectMeta ( & scale . ObjectMeta , true , apivalidation . NameIsDNSSubdomain , field . NewPath ( "metadata" ) ) ... )
2015-11-02 18:50:43 +00:00
if scale . Spec . Replicas < 0 {
2015-11-14 20:26:04 +00:00
allErrs = append ( allErrs , field . Invalid ( field . NewPath ( "spec" , "replicas" ) , scale . Spec . Replicas , "must be greater than or equal to 0" ) )
2015-11-02 18:50:43 +00:00
}
return allErrs
}
2015-03-31 21:36:25 +00:00
// ValidateConfigMapName can be used to check whether the given ConfigMap name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidateConfigMapName ( name string , prefix bool ) ( bool , string ) {
return apivalidation . NameIsDNSSubdomain ( name , prefix )
}
// ValidateConfigMap tests whether required fields in the ConfigMap are set.
func ValidateConfigMap ( cfg * extensions . ConfigMap ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , apivalidation . ValidateObjectMeta ( & cfg . ObjectMeta , true , ValidateConfigMapName , field . NewPath ( "metadata" ) ) ... )
for key := range cfg . Data {
if ! apivalidation . IsSecretKey ( key ) {
allErrs = append ( allErrs , field . Invalid ( field . NewPath ( "data" ) . Key ( key ) , key , fmt . Sprintf ( "must have at most %d characters and match regex %s" , validation . DNS1123SubdomainMaxLength , apivalidation . SecretKeyFmt ) ) )
}
}
return allErrs
}
// ValidateConfigMapUpdate tests if required fields in the ConfigMap are set.
func ValidateConfigMapUpdate ( newCfg , oldCfg * extensions . ConfigMap ) field . ErrorList {
allErrs := field . ErrorList { }
allErrs = append ( allErrs , apivalidation . ValidateObjectMetaUpdate ( & newCfg . ObjectMeta , & oldCfg . ObjectMeta , field . NewPath ( "metadata" ) ) ... )
allErrs = append ( allErrs , ValidateConfigMap ( newCfg ) ... )
return allErrs
}