|
|
|
@ -38,9 +38,9 @@ func intervalErrorMsg(lo, hi int) string {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var labelValueErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.LabelValueMaxLength, util.LabelValueFmt)
|
|
|
|
|
var qualifiedNameErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS1123SubdomainMaxLength, util.QualifiedNameFmt)
|
|
|
|
|
var qualifiedNameErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.QualifiedNameMaxLength, util.QualifiedNameFmt)
|
|
|
|
|
var dnsSubdomainErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS1123SubdomainMaxLength, util.DNS1123SubdomainFmt)
|
|
|
|
|
var dnsLabelErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS1123LabelMaxLength, util.DNS1123LabelFmt)
|
|
|
|
|
var dns1123LabelErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS1123LabelMaxLength, util.DNS1123LabelFmt)
|
|
|
|
|
var dns952LabelErrorMsg string = fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS952LabelMaxLength, util.DNS952LabelFmt)
|
|
|
|
|
var pdPartitionErrorMsg string = intervalErrorMsg(0, 255)
|
|
|
|
|
var portRangeErrorMsg string = intervalErrorMsg(0, 65536)
|
|
|
|
@ -157,7 +157,7 @@ func nameIsDNSSubdomain(name string, prefix bool) (bool, string) {
|
|
|
|
|
if prefix {
|
|
|
|
|
name = maskTrailingDash(name)
|
|
|
|
|
}
|
|
|
|
|
if util.IsDNSSubdomain(name) {
|
|
|
|
|
if util.IsDNS1123Subdomain(name) {
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
return false, dnsSubdomainErrorMsg
|
|
|
|
@ -187,7 +187,7 @@ func ValidateObjectMeta(meta *api.ObjectMeta, requiresNamespace bool, nameFn Val
|
|
|
|
|
// if the generated name validates, but the calculated value does not, it's a problem with generation, and we
|
|
|
|
|
// report it here. This may confuse users, but indicates a programming bug and still must be validated.
|
|
|
|
|
if len(meta.Name) == 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("name", meta.Name))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else {
|
|
|
|
|
if ok, qualifier := nameFn(meta.Name, false); !ok {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("name", meta.Name, qualifier))
|
|
|
|
@ -196,8 +196,8 @@ func ValidateObjectMeta(meta *api.ObjectMeta, requiresNamespace bool, nameFn Val
|
|
|
|
|
|
|
|
|
|
if requiresNamespace {
|
|
|
|
|
if len(meta.Namespace) == 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("namespace", meta.Namespace))
|
|
|
|
|
} else if !util.IsDNSSubdomain(meta.Namespace) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("namespace"))
|
|
|
|
|
} else if !util.IsDNS1123Subdomain(meta.Namespace) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", meta.Namespace, dnsSubdomainErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -252,9 +252,9 @@ func validateVolumes(volumes []api.Volume) (util.StringSet, errs.ValidationError
|
|
|
|
|
for i, vol := range volumes {
|
|
|
|
|
el := validateSource(&vol.VolumeSource).Prefix("source")
|
|
|
|
|
if len(vol.Name) == 0 {
|
|
|
|
|
el = append(el, errs.NewFieldRequired("name", vol.Name))
|
|
|
|
|
} else if !util.IsDNSLabel(vol.Name) {
|
|
|
|
|
el = append(el, errs.NewFieldInvalid("name", vol.Name, dnsLabelErrorMsg))
|
|
|
|
|
el = append(el, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !util.IsDNS1123Label(vol.Name) {
|
|
|
|
|
el = append(el, errs.NewFieldInvalid("name", vol.Name, dns1123LabelErrorMsg))
|
|
|
|
|
} else if allNames.Has(vol.Name) {
|
|
|
|
|
el = append(el, errs.NewFieldDuplicate("name", vol.Name))
|
|
|
|
|
}
|
|
|
|
@ -299,7 +299,7 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
|
|
|
|
|
func validateHostPathVolumeSource(hostDir *api.HostPathVolumeSource) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if hostDir.Path == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("path", hostDir.Path))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("path"))
|
|
|
|
|
}
|
|
|
|
|
return allErrs
|
|
|
|
|
}
|
|
|
|
@ -307,7 +307,7 @@ func validateHostPathVolumeSource(hostDir *api.HostPathVolumeSource) errs.Valida
|
|
|
|
|
func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if gitRepo.Repository == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("repository", gitRepo.Repository))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("repository"))
|
|
|
|
|
}
|
|
|
|
|
return allErrs
|
|
|
|
|
}
|
|
|
|
@ -315,10 +315,10 @@ func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) errs.Validati
|
|
|
|
|
func validateGCEPersistentDiskVolumeSource(PD *api.GCEPersistentDiskVolumeSource) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if PD.PDName == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("pdName", PD.PDName))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("pdName"))
|
|
|
|
|
}
|
|
|
|
|
if PD.FSType == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("fsType", PD.FSType))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("fsType"))
|
|
|
|
|
}
|
|
|
|
|
if PD.Partition < 0 || PD.Partition > 255 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("partition", PD.Partition, pdPartitionErrorMsg))
|
|
|
|
@ -329,10 +329,10 @@ func validateGCEPersistentDiskVolumeSource(PD *api.GCEPersistentDiskVolumeSource
|
|
|
|
|
func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if secretSource.Target.Name == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("target.name", ""))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("target.name"))
|
|
|
|
|
}
|
|
|
|
|
if secretSource.Target.Namespace == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("target.namespace", ""))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("target.namespace"))
|
|
|
|
|
}
|
|
|
|
|
if secretSource.Target.Kind != "Secret" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("target.kind", secretSource.Target.Kind, "Secret"))
|
|
|
|
@ -349,8 +349,8 @@ func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
|
|
|
|
|
for i, port := range ports {
|
|
|
|
|
pErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(port.Name) > 0 {
|
|
|
|
|
if len(port.Name) > util.DNS1123LabelMaxLength || !util.IsDNSLabel(port.Name) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, dnsLabelErrorMsg))
|
|
|
|
|
if len(port.Name) > util.DNS1123LabelMaxLength || !util.IsDNS1123Label(port.Name) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, dns1123LabelErrorMsg))
|
|
|
|
|
} else if allNames.Has(port.Name) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldDuplicate("name", port.Name))
|
|
|
|
|
} else {
|
|
|
|
@ -366,7 +366,7 @@ func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("hostPort", port.HostPort, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if len(port.Protocol) == 0 {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldRequired("protocol", port.Protocol))
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldRequired("protocol"))
|
|
|
|
|
} else if !supportedPortProtocols.Has(strings.ToUpper(string(port.Protocol))) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldNotSupported("protocol", port.Protocol))
|
|
|
|
|
}
|
|
|
|
@ -381,7 +381,7 @@ func validateEnv(vars []api.EnvVar) errs.ValidationErrorList {
|
|
|
|
|
for i, ev := range vars {
|
|
|
|
|
vErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(ev.Name) == 0 {
|
|
|
|
|
vErrs = append(vErrs, errs.NewFieldRequired("name", ev.Name))
|
|
|
|
|
vErrs = append(vErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
}
|
|
|
|
|
if !util.IsCIdentifier(ev.Name) {
|
|
|
|
|
vErrs = append(vErrs, errs.NewFieldInvalid("name", ev.Name, cIdentifierErrorMsg))
|
|
|
|
@ -397,12 +397,12 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs
|
|
|
|
|
for i, mnt := range mounts {
|
|
|
|
|
mErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(mnt.Name) == 0 {
|
|
|
|
|
mErrs = append(mErrs, errs.NewFieldRequired("name", mnt.Name))
|
|
|
|
|
mErrs = append(mErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !volumes.Has(mnt.Name) {
|
|
|
|
|
mErrs = append(mErrs, errs.NewFieldNotFound("name", mnt.Name))
|
|
|
|
|
}
|
|
|
|
|
if len(mnt.MountPath) == 0 {
|
|
|
|
|
mErrs = append(mErrs, errs.NewFieldRequired("mountPath", mnt.MountPath))
|
|
|
|
|
mErrs = append(mErrs, errs.NewFieldRequired("mountPath"))
|
|
|
|
|
}
|
|
|
|
|
allErrs = append(allErrs, mErrs.PrefixIndex(i)...)
|
|
|
|
|
}
|
|
|
|
@ -458,7 +458,7 @@ func checkHostPortConflicts(containers []api.Container) errs.ValidationErrorList
|
|
|
|
|
func validateExecAction(exec *api.ExecAction) errs.ValidationErrorList {
|
|
|
|
|
allErrors := errs.ValidationErrorList{}
|
|
|
|
|
if len(exec.Command) == 0 {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("command", exec.Command))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("command"))
|
|
|
|
|
}
|
|
|
|
|
return allErrors
|
|
|
|
|
}
|
|
|
|
@ -466,12 +466,12 @@ func validateExecAction(exec *api.ExecAction) errs.ValidationErrorList {
|
|
|
|
|
func validateHTTPGetAction(http *api.HTTPGetAction) errs.ValidationErrorList {
|
|
|
|
|
allErrors := errs.ValidationErrorList{}
|
|
|
|
|
if len(http.Path) == 0 {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("path", http.Path))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("path"))
|
|
|
|
|
}
|
|
|
|
|
if http.Port.Kind == util.IntstrInt && !util.IsValidPortNum(http.Port.IntVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", http.Port, portRangeErrorMsg))
|
|
|
|
|
} else if http.Port.Kind == util.IntstrString && len(http.Port.StrVal) == 0 {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("port", http.Port.StrVal))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("port"))
|
|
|
|
|
}
|
|
|
|
|
return allErrors
|
|
|
|
|
}
|
|
|
|
@ -481,7 +481,7 @@ func validateTCPSocketAction(tcp *api.TCPSocketAction) errs.ValidationErrorList
|
|
|
|
|
if tcp.Port.Kind == util.IntstrInt && !util.IsValidPortNum(tcp.Port.IntVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", tcp.Port, portRangeErrorMsg))
|
|
|
|
|
} else if tcp.Port.Kind == util.IntstrString && len(tcp.Port.StrVal) == 0 {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("port", tcp.Port.StrVal))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("port"))
|
|
|
|
|
}
|
|
|
|
|
return allErrors
|
|
|
|
|
}
|
|
|
|
@ -525,7 +525,7 @@ func validatePullPolicy(ctr *api.Container) errs.ValidationErrorList {
|
|
|
|
|
case api.PullAlways, api.PullIfNotPresent, api.PullNever:
|
|
|
|
|
break
|
|
|
|
|
case "":
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("", ctr.ImagePullPolicy))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired(""))
|
|
|
|
|
default:
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldNotSupported("", ctr.ImagePullPolicy))
|
|
|
|
|
}
|
|
|
|
@ -541,9 +541,9 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
|
|
|
|
|
cErrs := errs.ValidationErrorList{}
|
|
|
|
|
capabilities := capabilities.Get()
|
|
|
|
|
if len(ctr.Name) == 0 {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldRequired("name", ctr.Name))
|
|
|
|
|
} else if !util.IsDNSLabel(ctr.Name) {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name, dnsLabelErrorMsg))
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !util.IsDNS1123Label(ctr.Name) {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name, dns1123LabelErrorMsg))
|
|
|
|
|
} else if allNames.Has(ctr.Name) {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldDuplicate("name", ctr.Name))
|
|
|
|
|
} else if ctr.Privileged && !capabilities.AllowPrivileged {
|
|
|
|
@ -552,7 +552,7 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
|
|
|
|
|
allNames.Insert(ctr.Name)
|
|
|
|
|
}
|
|
|
|
|
if len(ctr.Image) == 0 {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldRequired("image", ctr.Image))
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldRequired("image"))
|
|
|
|
|
}
|
|
|
|
|
if ctr.Lifecycle != nil {
|
|
|
|
|
cErrs = append(cErrs, validateLifecycle(ctr.Lifecycle).Prefix("lifecycle")...)
|
|
|
|
@ -587,7 +587,7 @@ func ValidateManifest(manifest *api.ContainerManifest) errs.ValidationErrorList
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
|
|
|
|
|
if len(manifest.Version) == 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("version", manifest.Version))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("version"))
|
|
|
|
|
} else if !supportedManifestVersions.Has(strings.ToLower(manifest.Version)) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldNotSupported("version", manifest.Version))
|
|
|
|
|
}
|
|
|
|
@ -605,7 +605,7 @@ func validateRestartPolicy(restartPolicy *api.RestartPolicy) errs.ValidationErro
|
|
|
|
|
case api.RestartPolicyAlways, api.RestartPolicyOnFailure, api.RestartPolicyNever:
|
|
|
|
|
break
|
|
|
|
|
case "":
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("", *restartPolicy))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired(""))
|
|
|
|
|
default:
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldNotSupported("", restartPolicy))
|
|
|
|
|
}
|
|
|
|
@ -619,7 +619,7 @@ func validateDNSPolicy(dnsPolicy *api.DNSPolicy) errs.ValidationErrorList {
|
|
|
|
|
case api.DNSClusterFirst, api.DNSDefault:
|
|
|
|
|
break
|
|
|
|
|
case "":
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("", *dnsPolicy))
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired(""))
|
|
|
|
|
default:
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldNotSupported("", dnsPolicy))
|
|
|
|
|
}
|
|
|
|
@ -707,14 +707,14 @@ func ValidateService(service *api.Service) errs.ValidationErrorList {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("spec.port", service.Spec.Port, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if len(service.Spec.Protocol) == 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.protocol", service.Spec.Protocol))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.protocol"))
|
|
|
|
|
} else if !supportedPortProtocols.Has(strings.ToUpper(string(service.Spec.Protocol))) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldNotSupported("spec.protocol", service.Spec.Protocol))
|
|
|
|
|
}
|
|
|
|
|
if service.Spec.ContainerPort.Kind == util.IntstrInt && service.Spec.ContainerPort.IntVal != 0 && !util.IsValidPortNum(service.Spec.ContainerPort.IntVal) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("spec.containerPort", service.Spec.Port, portRangeErrorMsg))
|
|
|
|
|
} else if service.Spec.ContainerPort.Kind == util.IntstrString && len(service.Spec.ContainerPort.StrVal) == 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.containerPort", service.Spec.ContainerPort.StrVal))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.containerPort"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if service.Spec.Selector != nil {
|
|
|
|
@ -722,7 +722,7 @@ func ValidateService(service *api.Service) errs.ValidationErrorList {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if service.Spec.SessionAffinity == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.sessionAffinity", service.Spec.SessionAffinity))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("spec.sessionAffinity"))
|
|
|
|
|
} else if !supportedSessionAffinityType.Has(string(service.Spec.SessionAffinity)) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldNotSupported("spec.sessionAffinity", service.Spec.SessionAffinity))
|
|
|
|
|
}
|
|
|
|
@ -767,14 +767,14 @@ func ValidateReplicationControllerSpec(spec *api.ReplicationControllerSpec) errs
|
|
|
|
|
|
|
|
|
|
selector := labels.Set(spec.Selector).AsSelector()
|
|
|
|
|
if selector.Empty() {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("selector", spec.Selector))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("selector"))
|
|
|
|
|
}
|
|
|
|
|
if spec.Replicas < 0 {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("replicas", spec.Replicas, isNegativeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if spec.Template == nil {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("template", spec.Template))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("template"))
|
|
|
|
|
} else {
|
|
|
|
|
labels := labels.Set(spec.Template.Labels)
|
|
|
|
|
if !selector.Matches(labels) {
|
|
|
|
@ -893,7 +893,7 @@ func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
|
|
|
|
|
|
|
|
|
totalSize := 0
|
|
|
|
|
for key, value := range secret.Data {
|
|
|
|
|
if !util.IsDNSSubdomain(key) {
|
|
|
|
|
if !util.IsDNS1123Subdomain(key) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, cIdentifierErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|