mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #24799 from thockin/validation_pt8-2
Automatic merge from submit-queue Make IsValidLabelValue return error strings Part of the larger validation PR, broken out for easier review and merge. Builds on previous PRs in the series.
This commit is contained in:
commit
e4e6e46197
@ -181,12 +181,12 @@ func SlaveAttributesToLabels(attrs []*mesos.Attribute) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errs := validation.IsQualifiedName(k); len(errs) != 0 {
|
if errs := validation.IsQualifiedName(k); len(errs) != 0 {
|
||||||
log.V(3).Infof("ignoring invalid node label name %q", k, errs)
|
log.V(3).Infof("ignoring invalid node label %q: %v", k, errs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !validation.IsValidLabelValue(v) {
|
if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
|
||||||
log.V(3).Infof("ignoring invalid node label %s value: %q", k, v)
|
log.V(3).Infof("ignoring invalid node %s=%q: %v", k, v, errs)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,17 +17,11 @@ limitations under the License.
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/util/validation"
|
"k8s.io/kubernetes/pkg/util/validation"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, validation.LabelValueMaxLength, validation.LabelValueFmt)
|
|
||||||
)
|
|
||||||
|
|
||||||
func ValidateLabelSelector(ps *unversioned.LabelSelector, fldPath *field.Path) field.ErrorList {
|
func ValidateLabelSelector(ps *unversioned.LabelSelector, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
if ps == nil {
|
if ps == nil {
|
||||||
@ -72,8 +66,8 @@ func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorLi
|
|||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
for k, v := range labels {
|
for k, v := range labels {
|
||||||
allErrs = append(allErrs, ValidateLabelName(k, fldPath)...)
|
allErrs = append(allErrs, ValidateLabelName(k, fldPath)...)
|
||||||
if !validation.IsValidLabelValue(v) {
|
for _, err := range validation.IsValidLabelValue(v) {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, v, labelValueErrorMsg))
|
allErrs = append(allErrs, field.Invalid(fldPath, v, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
|
@ -67,20 +67,22 @@ func TestValidateLabels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
labelValueErrorCases := []map[string]string{
|
labelValueErrorCases := []struct {
|
||||||
{"toolongvalue": strings.Repeat("a", 64)},
|
labels map[string]string
|
||||||
{"backslashesinvalue": "some\\bad\\value"},
|
expect string
|
||||||
{"nocommasallowed": "bad,value"},
|
}{
|
||||||
{"strangecharsinvalue": "?#$notsogood"},
|
{map[string]string{"toolongvalue": strings.Repeat("a", 64)}, "must be no more than"},
|
||||||
|
{map[string]string{"backslashesinvalue": "some\\bad\\value"}, "must match the regex"},
|
||||||
|
{map[string]string{"nocommasallowed": "bad,value"}, "must match the regex"},
|
||||||
|
{map[string]string{"strangecharsinvalue": "?#$notsogood"}, "must match the regex"},
|
||||||
}
|
}
|
||||||
for i := range labelValueErrorCases {
|
for i := range labelValueErrorCases {
|
||||||
errs := ValidateLabels(labelValueErrorCases[i], field.NewPath("field"))
|
errs := ValidateLabels(labelValueErrorCases[i].labels, field.NewPath("field"))
|
||||||
if len(errs) != 1 {
|
if len(errs) != 1 {
|
||||||
t.Errorf("case[%d] expected failure", i)
|
t.Errorf("case[%d]: expected failure", i)
|
||||||
} else {
|
} else {
|
||||||
detail := errs[0].Detail
|
if !strings.Contains(errs[0].Detail, labelValueErrorCases[i].expect) {
|
||||||
if detail != labelValueErrorMsg {
|
t.Errorf("case[%d]: error details do not include %q: %q", i, labelValueErrorCases[i].expect, errs[0].Detail)
|
||||||
t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ func InclusiveRangeErrorMsg(lo, hi int) string {
|
|||||||
return fmt.Sprintf(`must be between %d and %d, inclusive`, lo, hi)
|
return fmt.Sprintf(`must be between %d and %d, inclusive`, lo, hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
var labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, validation.LabelValueMaxLength, validation.LabelValueFmt)
|
|
||||||
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 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 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 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)
|
||||||
|
@ -124,9 +124,12 @@ func parseLabels(spec []string) (map[string]string, []string, error) {
|
|||||||
for _, labelSpec := range spec {
|
for _, labelSpec := range spec {
|
||||||
if strings.Index(labelSpec, "=") != -1 {
|
if strings.Index(labelSpec, "=") != -1 {
|
||||||
parts := strings.Split(labelSpec, "=")
|
parts := strings.Split(labelSpec, "=")
|
||||||
if len(parts) != 2 || len(parts[1]) == 0 || !validation.IsValidLabelValue(parts[1]) {
|
if len(parts) != 2 || len(parts[1]) == 0 {
|
||||||
return nil, nil, fmt.Errorf("invalid label spec: %v", labelSpec)
|
return nil, nil, fmt.Errorf("invalid label spec: %v", labelSpec)
|
||||||
}
|
}
|
||||||
|
if errs := validation.IsValidLabelValue(parts[1]); len(errs) != 0 {
|
||||||
|
return nil, nil, fmt.Errorf("invalid label value: %q: %s", labelSpec, strings.Join(errs, ";"))
|
||||||
|
}
|
||||||
labels[parts[0]] = parts[1]
|
labels[parts[0]] = parts[1]
|
||||||
} else if strings.HasSuffix(labelSpec, "-") {
|
} else if strings.HasSuffix(labelSpec, "-") {
|
||||||
remove = append(remove, labelSpec[:len(labelSpec)-1])
|
remove = append(remove, labelSpec[:len(labelSpec)-1])
|
||||||
|
@ -120,8 +120,8 @@ func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host H
|
|||||||
allErrs := []error{}
|
allErrs := []error{}
|
||||||
for _, plugin := range plugins {
|
for _, plugin := range plugins {
|
||||||
name := plugin.Name()
|
name := plugin.Name()
|
||||||
if len(validation.IsQualifiedName(name)) != 0 {
|
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
|
||||||
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %#v", plugin))
|
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,8 +764,6 @@ func parse(selector string) (internalSelector, error) {
|
|||||||
return internalSelector(items), err
|
return internalSelector(items), err
|
||||||
}
|
}
|
||||||
|
|
||||||
var labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, validation.LabelValueMaxLength, validation.LabelValueFmt)
|
|
||||||
|
|
||||||
func validateLabelKey(k string) error {
|
func validateLabelKey(k string) error {
|
||||||
if errs := validation.IsQualifiedName(k); len(errs) != 0 {
|
if errs := validation.IsQualifiedName(k); len(errs) != 0 {
|
||||||
return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; "))
|
return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; "))
|
||||||
@ -774,8 +772,8 @@ func validateLabelKey(k string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateLabelValue(v string) error {
|
func validateLabelValue(v string) error {
|
||||||
if !validation.IsValidLabelValue(v) {
|
if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
|
||||||
return fmt.Errorf("invalid label value: %s", labelValueErrorMsg)
|
return fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; "))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -67,13 +67,24 @@ func IsQualifiedName(value string) []string {
|
|||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
const LabelValueFmt string = "(" + qualifiedNameFmt + ")?"
|
const labelValueFmt string = "(" + qualifiedNameFmt + ")?"
|
||||||
const LabelValueMaxLength int = 63
|
const LabelValueMaxLength int = 63
|
||||||
|
|
||||||
var labelValueRegexp = regexp.MustCompile("^" + LabelValueFmt + "$")
|
var labelValueMaxLengthString = strconv.Itoa(LabelValueMaxLength)
|
||||||
|
var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")
|
||||||
|
|
||||||
func IsValidLabelValue(value string) bool {
|
// IsValidLabelValue tests whether the value passed is a valid label value. If
|
||||||
return (len(value) <= LabelValueMaxLength && labelValueRegexp.MatchString(value))
|
// the value is not valid, a list of error strings is returned. Otherwise an
|
||||||
|
// empty list (or nil) is returned.
|
||||||
|
func IsValidLabelValue(value string) []string {
|
||||||
|
var errs []string
|
||||||
|
if len(value) > LabelValueMaxLength {
|
||||||
|
errs = append(errs, "must be no more than "+labelValueMaxLengthString+" characters")
|
||||||
|
}
|
||||||
|
if !labelValueRegexp.MatchString(value) {
|
||||||
|
errs = append(errs, "must match the regex "+labelValueFmt+" (e.g. 'MyValue' or 'my_value' or '12345')")
|
||||||
|
}
|
||||||
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
const DNS1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
|
const DNS1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
|
||||||
|
@ -257,8 +257,8 @@ func TestIsValidLabelValue(t *testing.T) {
|
|||||||
"", // empty value
|
"", // empty value
|
||||||
}
|
}
|
||||||
for i := range successCases {
|
for i := range successCases {
|
||||||
if !IsValidLabelValue(successCases[i]) {
|
if errs := IsValidLabelValue(successCases[i]); len(errs) != 0 {
|
||||||
t.Errorf("case %s expected success", successCases[i])
|
t.Errorf("case %s expected success: %v", successCases[i], errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ func TestIsValidLabelValue(t *testing.T) {
|
|||||||
strings.Repeat("a", 64), // over the limit
|
strings.Repeat("a", 64), // over the limit
|
||||||
}
|
}
|
||||||
for i := range errorCases {
|
for i := range errorCases {
|
||||||
if IsValidLabelValue(errorCases[i]) {
|
if errs := IsValidLabelValue(errorCases[i]); len(errs) == 0 {
|
||||||
t.Errorf("case[%d] expected failure", i)
|
t.Errorf("case[%d] expected failure", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,8 +272,8 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost)
|
|||||||
allErrs := []error{}
|
allErrs := []error{}
|
||||||
for _, plugin := range plugins {
|
for _, plugin := range plugins {
|
||||||
name := plugin.Name()
|
name := plugin.Name()
|
||||||
if len(validation.IsQualifiedName(name)) != 0 {
|
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
|
||||||
allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %#v", plugin))
|
allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,8 +307,8 @@ func (f *ConfigFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String,
|
|||||||
|
|
||||||
failureDomainArgs := strings.Split(f.FailureDomains, ",")
|
failureDomainArgs := strings.Split(f.FailureDomains, ",")
|
||||||
for _, failureDomain := range failureDomainArgs {
|
for _, failureDomain := range failureDomainArgs {
|
||||||
if len(utilvalidation.IsQualifiedName(failureDomain)) != 0 {
|
if errs := utilvalidation.IsQualifiedName(failureDomain); len(errs) != 0 {
|
||||||
return nil, fmt.Errorf("invalid failure domain: %s", failureDomain)
|
return nil, fmt.Errorf("invalid failure domain: %q: %s", failureDomain, strings.Join(errs, ";"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user