|
|
|
@ -33,31 +33,32 @@ import (
|
|
|
|
|
"k8s.io/kubernetes/pkg/util"
|
|
|
|
|
errs "k8s.io/kubernetes/pkg/util/fielderrors"
|
|
|
|
|
"k8s.io/kubernetes/pkg/util/sets"
|
|
|
|
|
"k8s.io/kubernetes/pkg/util/validation"
|
|
|
|
|
|
|
|
|
|
"github.com/golang/glog"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const cIdentifierErrorMsg string = `must be a C identifier (matching regex ` + util.CIdentifierFmt + `): e.g. "my_name" or "MyName"`
|
|
|
|
|
const cIdentifierErrorMsg string = `must be a C identifier (matching regex ` + validation.CIdentifierFmt + `): e.g. "my_name" or "MyName"`
|
|
|
|
|
const isNegativeErrorMsg string = `must be non-negative`
|
|
|
|
|
|
|
|
|
|
func intervalErrorMsg(lo, hi int) string {
|
|
|
|
|
return fmt.Sprintf(`must be greater than %d and less than %d`, lo, hi)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, util.LabelValueMaxLength, util.LabelValueFmt)
|
|
|
|
|
var qualifiedNameErrorMsg string = fmt.Sprintf(`must be a qualified name (at most %d characters, matching regex %s), with an optional DNS subdomain prefix (at most %d characters, matching regex %s) and slash (/): e.g. "MyName" or "example.com/MyName"`, util.QualifiedNameMaxLength, util.QualifiedNameFmt, util.DNS1123SubdomainMaxLength, util.DNS1123SubdomainFmt)
|
|
|
|
|
var DNSSubdomainErrorMsg string = fmt.Sprintf(`must be a DNS subdomain (at most %d characters, matching regex %s): e.g. "example.com"`, util.DNS1123SubdomainMaxLength, util.DNS1123SubdomainFmt)
|
|
|
|
|
var DNS1123LabelErrorMsg string = fmt.Sprintf(`must be a DNS label (at most %d characters, matching regex %s): e.g. "my-name"`, util.DNS1123LabelMaxLength, util.DNS1123LabelFmt)
|
|
|
|
|
var DNS952LabelErrorMsg string = fmt.Sprintf(`must be a DNS 952 label (at most %d characters, matching regex %s): e.g. "my-name"`, util.DNS952LabelMaxLength, util.DNS952LabelFmt)
|
|
|
|
|
var labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, validation.LabelValueMaxLength, validation.LabelValueFmt)
|
|
|
|
|
var qualifiedNameErrorMsg string = fmt.Sprintf(`must be a qualified name (at most %d characters, matching regex %s), with an optional DNS subdomain prefix (at most %d characters, matching regex %s) and slash (/): e.g. "MyName" or "example.com/MyName"`, validation.QualifiedNameMaxLength, validation.QualifiedNameFmt, validation.DNS1123SubdomainMaxLength, validation.DNS1123SubdomainFmt)
|
|
|
|
|
var DNSSubdomainErrorMsg string = fmt.Sprintf(`must be a DNS subdomain (at most %d characters, matching regex %s): e.g. "example.com"`, validation.DNS1123SubdomainMaxLength, validation.DNS1123SubdomainFmt)
|
|
|
|
|
var DNS1123LabelErrorMsg string = fmt.Sprintf(`must be a DNS label (at most %d characters, matching regex %s): e.g. "my-name"`, validation.DNS1123LabelMaxLength, validation.DNS1123LabelFmt)
|
|
|
|
|
var DNS952LabelErrorMsg string = fmt.Sprintf(`must be a DNS 952 label (at most %d characters, matching regex %s): e.g. "my-name"`, validation.DNS952LabelMaxLength, validation.DNS952LabelFmt)
|
|
|
|
|
var pdPartitionErrorMsg string = intervalErrorMsg(0, 255)
|
|
|
|
|
var portRangeErrorMsg string = intervalErrorMsg(0, 65536)
|
|
|
|
|
var portNameErrorMsg string = fmt.Sprintf(`must be an IANA_SVC_NAME (at most 15 characters, matching regex %s, it must contain at least one letter [a-z], and hyphens cannot be adjacent to other hyphens): e.g. "http"`, util.IdentifierNoHyphensBeginEndFmt)
|
|
|
|
|
var portNameErrorMsg string = fmt.Sprintf(`must be an IANA_SVC_NAME (at most 15 characters, matching regex %s, it must contain at least one letter [a-z], and hyphens cannot be adjacent to other hyphens): e.g. "http"`, validation.IdentifierNoHyphensBeginEndFmt)
|
|
|
|
|
|
|
|
|
|
const totalAnnotationSizeLimitB int = 64 * (1 << 10) // 64 kB
|
|
|
|
|
|
|
|
|
|
func ValidateLabelName(labelName, fieldName string) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if !util.IsQualifiedName(labelName) {
|
|
|
|
|
if !validation.IsQualifiedName(labelName) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(fieldName, labelName, qualifiedNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
return allErrs
|
|
|
|
@ -68,7 +69,7 @@ func ValidateLabels(labels map[string]string, field string) errs.ValidationError
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
for k, v := range labels {
|
|
|
|
|
allErrs = append(allErrs, ValidateLabelName(k, field)...)
|
|
|
|
|
if !util.IsValidLabelValue(v) {
|
|
|
|
|
if !validation.IsValidLabelValue(v) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(field, v, labelValueErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -80,7 +81,7 @@ func ValidateAnnotations(annotations map[string]string, field string) errs.Valid
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
var totalSize int64
|
|
|
|
|
for k, v := range annotations {
|
|
|
|
|
if !util.IsQualifiedName(strings.ToLower(k)) {
|
|
|
|
|
if !validation.IsQualifiedName(strings.ToLower(k)) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(field, k, qualifiedNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
totalSize += (int64)(len(k)) + (int64)(len(v))
|
|
|
|
@ -182,7 +183,7 @@ func NameIsDNSSubdomain(name string, prefix bool) (bool, string) {
|
|
|
|
|
if prefix {
|
|
|
|
|
name = maskTrailingDash(name)
|
|
|
|
|
}
|
|
|
|
|
if util.IsDNS1123Subdomain(name) {
|
|
|
|
|
if validation.IsDNS1123Subdomain(name) {
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
return false, DNSSubdomainErrorMsg
|
|
|
|
@ -193,7 +194,7 @@ func NameIsDNSLabel(name string, prefix bool) (bool, string) {
|
|
|
|
|
if prefix {
|
|
|
|
|
name = maskTrailingDash(name)
|
|
|
|
|
}
|
|
|
|
|
if util.IsDNS1123Label(name) {
|
|
|
|
|
if validation.IsDNS1123Label(name) {
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
return false, DNS1123LabelErrorMsg
|
|
|
|
@ -204,7 +205,7 @@ func NameIsDNS952Label(name string, prefix bool) (bool, string) {
|
|
|
|
|
if prefix {
|
|
|
|
|
name = maskTrailingDash(name)
|
|
|
|
|
}
|
|
|
|
|
if util.IsDNS952Label(name) {
|
|
|
|
|
if validation.IsDNS952Label(name) {
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
return false, DNS952LabelErrorMsg
|
|
|
|
@ -316,7 +317,7 @@ func validateVolumes(volumes []api.Volume) (sets.String, errs.ValidationErrorLis
|
|
|
|
|
el := validateSource(&vol.VolumeSource).Prefix("source")
|
|
|
|
|
if len(vol.Name) == 0 {
|
|
|
|
|
el = append(el, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !util.IsDNS1123Label(vol.Name) {
|
|
|
|
|
} else if !validation.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))
|
|
|
|
@ -698,7 +699,7 @@ func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
|
|
|
|
|
for i, port := range ports {
|
|
|
|
|
pErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(port.Name) > 0 {
|
|
|
|
|
if !util.IsValidPortName(port.Name) {
|
|
|
|
|
if !validation.IsValidPortName(port.Name) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, portNameErrorMsg))
|
|
|
|
|
} else if allNames.Has(port.Name) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldDuplicate("name", port.Name))
|
|
|
|
@ -708,10 +709,10 @@ func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
|
|
|
|
|
}
|
|
|
|
|
if port.ContainerPort == 0 {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("containerPort", port.ContainerPort, portRangeErrorMsg))
|
|
|
|
|
} else if !util.IsValidPortNum(port.ContainerPort) {
|
|
|
|
|
} else if !validation.IsValidPortNum(port.ContainerPort) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("containerPort", port.ContainerPort, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if port.HostPort != 0 && !util.IsValidPortNum(port.HostPort) {
|
|
|
|
|
if port.HostPort != 0 && !validation.IsValidPortNum(port.HostPort) {
|
|
|
|
|
pErrs = append(pErrs, errs.NewFieldInvalid("hostPort", port.HostPort, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if len(port.Protocol) == 0 {
|
|
|
|
@ -731,7 +732,7 @@ func validateEnv(vars []api.EnvVar) errs.ValidationErrorList {
|
|
|
|
|
vErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(ev.Name) == 0 {
|
|
|
|
|
vErrs = append(vErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !util.IsCIdentifier(ev.Name) {
|
|
|
|
|
} else if !validation.IsCIdentifier(ev.Name) {
|
|
|
|
|
vErrs = append(vErrs, errs.NewFieldInvalid("name", ev.Name, cIdentifierErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
vErrs = append(vErrs, validateEnvVarValueFrom(ev).Prefix("valueFrom")...)
|
|
|
|
@ -861,9 +862,9 @@ func validateHTTPGetAction(http *api.HTTPGetAction) errs.ValidationErrorList {
|
|
|
|
|
if len(http.Path) == 0 {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldRequired("path"))
|
|
|
|
|
}
|
|
|
|
|
if http.Port.Kind == util.IntstrInt && !util.IsValidPortNum(http.Port.IntVal) {
|
|
|
|
|
if http.Port.Kind == util.IntstrInt && !validation.IsValidPortNum(http.Port.IntVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", http.Port, portRangeErrorMsg))
|
|
|
|
|
} else if http.Port.Kind == util.IntstrString && !util.IsValidPortName(http.Port.StrVal) {
|
|
|
|
|
} else if http.Port.Kind == util.IntstrString && !validation.IsValidPortName(http.Port.StrVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", http.Port.StrVal, portNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
supportedSchemes := sets.NewString(string(api.URISchemeHTTP), string(api.URISchemeHTTPS))
|
|
|
|
@ -875,9 +876,9 @@ func validateHTTPGetAction(http *api.HTTPGetAction) errs.ValidationErrorList {
|
|
|
|
|
|
|
|
|
|
func validateTCPSocketAction(tcp *api.TCPSocketAction) errs.ValidationErrorList {
|
|
|
|
|
allErrors := errs.ValidationErrorList{}
|
|
|
|
|
if tcp.Port.Kind == util.IntstrInt && !util.IsValidPortNum(tcp.Port.IntVal) {
|
|
|
|
|
if tcp.Port.Kind == util.IntstrInt && !validation.IsValidPortNum(tcp.Port.IntVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", tcp.Port, portRangeErrorMsg))
|
|
|
|
|
} else if tcp.Port.Kind == util.IntstrString && !util.IsValidPortName(tcp.Port.StrVal) {
|
|
|
|
|
} else if tcp.Port.Kind == util.IntstrString && !validation.IsValidPortName(tcp.Port.StrVal) {
|
|
|
|
|
allErrors = append(allErrors, errs.NewFieldInvalid("port", tcp.Port.StrVal, portNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
return allErrors
|
|
|
|
@ -943,7 +944,7 @@ func validateContainers(containers []api.Container, volumes sets.String) errs.Va
|
|
|
|
|
cErrs := errs.ValidationErrorList{}
|
|
|
|
|
if len(ctr.Name) == 0 {
|
|
|
|
|
cErrs = append(cErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if !util.IsDNS1123Label(ctr.Name) {
|
|
|
|
|
} else if !validation.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))
|
|
|
|
@ -1227,7 +1228,7 @@ func validateServicePort(sp *api.ServicePort, requireName bool, allNames *sets.S
|
|
|
|
|
if requireName && sp.Name == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if sp.Name != "" {
|
|
|
|
|
if !util.IsDNS1123Label(sp.Name) {
|
|
|
|
|
if !validation.IsDNS1123Label(sp.Name) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("name", sp.Name, DNS1123LabelErrorMsg))
|
|
|
|
|
} else if allNames.Has(sp.Name) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldDuplicate("name", sp.Name))
|
|
|
|
@ -1236,7 +1237,7 @@ func validateServicePort(sp *api.ServicePort, requireName bool, allNames *sets.S
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !util.IsValidPortNum(sp.Port) {
|
|
|
|
|
if !validation.IsValidPortNum(sp.Port) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("port", sp.Port, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1246,10 +1247,10 @@ func validateServicePort(sp *api.ServicePort, requireName bool, allNames *sets.S
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldValueNotSupported("protocol", sp.Protocol, supportedPortProtocols.List()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sp.TargetPort.Kind == util.IntstrInt && !util.IsValidPortNum(sp.TargetPort.IntVal) {
|
|
|
|
|
if sp.TargetPort.Kind == util.IntstrInt && !validation.IsValidPortNum(sp.TargetPort.IntVal) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("targetPort", sp.TargetPort, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if sp.TargetPort.Kind == util.IntstrString && !util.IsValidPortName(sp.TargetPort.StrVal) {
|
|
|
|
|
if sp.TargetPort.Kind == util.IntstrString && !validation.IsValidPortName(sp.TargetPort.StrVal) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("targetPort", sp.TargetPort, portNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1414,7 +1415,7 @@ func ValidateNodeUpdate(oldNode *api.Node, node *api.Node) errs.ValidationErrorL
|
|
|
|
|
// Refer to docs/resources.md for more details.
|
|
|
|
|
func validateResourceName(value string, field string) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if !util.IsQualifiedName(value) {
|
|
|
|
|
if !validation.IsQualifiedName(value) {
|
|
|
|
|
return append(allErrs, errs.NewFieldInvalid(field, value, "resource typename: "+qualifiedNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1522,14 +1523,14 @@ func ValidateServiceAccountUpdate(oldServiceAccount, newServiceAccount *api.Serv
|
|
|
|
|
return allErrs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SecretKeyFmt string = "\\.?" + util.DNS1123LabelFmt + "(\\." + util.DNS1123LabelFmt + ")*"
|
|
|
|
|
const SecretKeyFmt string = "\\.?" + validation.DNS1123LabelFmt + "(\\." + validation.DNS1123LabelFmt + ")*"
|
|
|
|
|
|
|
|
|
|
var secretKeyRegexp = regexp.MustCompile("^" + SecretKeyFmt + "$")
|
|
|
|
|
|
|
|
|
|
// IsSecretKey tests for a string that conforms to the definition of a
|
|
|
|
|
// subdomain in DNS (RFC 1123), except that a leading dot is allowed
|
|
|
|
|
func IsSecretKey(value string) bool {
|
|
|
|
|
return len(value) <= util.DNS1123SubdomainMaxLength && secretKeyRegexp.MatchString(value)
|
|
|
|
|
return len(value) <= validation.DNS1123SubdomainMaxLength && secretKeyRegexp.MatchString(value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ValidateSecret tests if required fields in the Secret are set.
|
|
|
|
@ -1540,7 +1541,7 @@ func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
|
|
|
|
totalSize := 0
|
|
|
|
|
for key, value := range secret.Data {
|
|
|
|
|
if !IsSecretKey(key) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, fmt.Sprintf("must have at most %d characters and match regex %s", util.DNS1123SubdomainMaxLength, SecretKeyFmt)))
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, fmt.Sprintf("must have at most %d characters and match regex %s", validation.DNS1123SubdomainMaxLength, SecretKeyFmt)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totalSize += len(value)
|
|
|
|
@ -1696,7 +1697,7 @@ func ValidateNamespace(namespace *api.Namespace) errs.ValidationErrorList {
|
|
|
|
|
// Validate finalizer names
|
|
|
|
|
func validateFinalizerName(stringValue string) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if !util.IsQualifiedName(stringValue) {
|
|
|
|
|
if !validation.IsQualifiedName(stringValue) {
|
|
|
|
|
return append(allErrs, errs.NewFieldInvalid("spec.finalizers", stringValue, qualifiedNameErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1786,7 +1787,7 @@ func validateEndpointSubsets(subsets []api.EndpointSubset) errs.ValidationErrorL
|
|
|
|
|
|
|
|
|
|
func validateEndpointAddress(address *api.EndpointAddress) errs.ValidationErrorList {
|
|
|
|
|
allErrs := errs.ValidationErrorList{}
|
|
|
|
|
if !util.IsValidIPv4(address.IP) {
|
|
|
|
|
if !validation.IsValidIPv4(address.IP) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("ip", address.IP, "invalid IPv4 address"))
|
|
|
|
|
return allErrs
|
|
|
|
|
}
|
|
|
|
@ -1819,11 +1820,11 @@ func validateEndpointPort(port *api.EndpointPort, requireName bool) errs.Validat
|
|
|
|
|
if requireName && port.Name == "" {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldRequired("name"))
|
|
|
|
|
} else if port.Name != "" {
|
|
|
|
|
if !util.IsDNS1123Label(port.Name) {
|
|
|
|
|
if !validation.IsDNS1123Label(port.Name) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("name", port.Name, DNS1123LabelErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !util.IsValidPortNum(port.Port) {
|
|
|
|
|
if !validation.IsValidPortNum(port.Port) {
|
|
|
|
|
allErrs = append(allErrs, errs.NewFieldInvalid("port", port.Port, portRangeErrorMsg))
|
|
|
|
|
}
|
|
|
|
|
if len(port.Protocol) == 0 {
|
|
|
|
|