Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make IsValidLabelValue return error strings #24799

Merged
merged 1 commit into from
May 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions contrib/mesos/pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,12 @@ func SlaveAttributesToLabels(attrs []*mesos.Attribute) map[string]string {
}

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
}

if !validation.IsValidLabelValue(v) {
log.V(3).Infof("ignoring invalid node label %s value: %q", k, v)
if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
log.V(3).Infof("ignoring invalid node %s=%q: %v", k, v, errs)
continue
}

Expand Down
10 changes: 2 additions & 8 deletions pkg/api/unversioned/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,11 @@ limitations under the License.
package validation

import (
"fmt"

"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/validation"
"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 {
allErrs := field.ErrorList{}
if ps == nil {
Expand Down Expand Up @@ -72,8 +66,8 @@ func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorLi
allErrs := field.ErrorList{}
for k, v := range labels {
allErrs = append(allErrs, ValidateLabelName(k, fldPath)...)
if !validation.IsValidLabelValue(v) {
allErrs = append(allErrs, field.Invalid(fldPath, v, labelValueErrorMsg))
for _, err := range validation.IsValidLabelValue(v) {
allErrs = append(allErrs, field.Invalid(fldPath, v, err))
}
}
return allErrs
Expand Down
22 changes: 12 additions & 10 deletions pkg/api/unversioned/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,22 @@ func TestValidateLabels(t *testing.T) {
}
}

labelValueErrorCases := []map[string]string{
{"toolongvalue": strings.Repeat("a", 64)},
{"backslashesinvalue": "some\\bad\\value"},
{"nocommasallowed": "bad,value"},
{"strangecharsinvalue": "?#$notsogood"},
labelValueErrorCases := []struct {
labels map[string]string
expect string
}{
{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 {
errs := ValidateLabels(labelValueErrorCases[i], field.NewPath("field"))
errs := ValidateLabels(labelValueErrorCases[i].labels, field.NewPath("field"))
if len(errs) != 1 {
t.Errorf("case[%d] expected failure", i)
t.Errorf("case[%d]: expected failure", i)
} else {
detail := errs[0].Detail
if detail != labelValueErrorMsg {
t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg)
if !strings.Contains(errs[0].Detail, labelValueErrorCases[i].expect) {
t.Errorf("case[%d]: error details do not include %q: %q", i, labelValueErrorCases[i].expect, errs[0].Detail)
}
}
}
Expand Down
1 change: 0 additions & 1 deletion pkg/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func InclusiveRangeErrorMsg(lo, hi int) string {
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 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)
Expand Down
5 changes: 4 additions & 1 deletion pkg/kubectl/cmd/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,12 @@ func parseLabels(spec []string) (map[string]string, []string, error) {
for _, labelSpec := range spec {
if strings.Index(labelSpec, "=") != -1 {
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)
}
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]
} else if strings.HasSuffix(labelSpec, "-") {
remove = append(remove, labelSpec[:len(labelSpec)-1])
Expand Down
4 changes: 2 additions & 2 deletions pkg/kubelet/network/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host H
allErrs := []error{}
for _, plugin := range plugins {
name := plugin.Name()
if len(validation.IsQualifiedName(name)) != 0 {
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %#v", plugin))
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
continue
}

Expand Down
6 changes: 2 additions & 4 deletions pkg/labels/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,6 @@ func parse(selector string) (internalSelector, error) {
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 {
if errs := validation.IsQualifiedName(k); len(errs) != 0 {
return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; "))
Expand All @@ -774,8 +772,8 @@ func validateLabelKey(k string) error {
}

func validateLabelValue(v string) error {
if !validation.IsValidLabelValue(v) {
return fmt.Errorf("invalid label value: %s", labelValueErrorMsg)
if errs := validation.IsValidLabelValue(v); len(errs) != 0 {
return fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; "))
}
return nil
}
Expand Down
19 changes: 15 additions & 4 deletions pkg/util/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,24 @@ func IsQualifiedName(value string) []string {
return errs
}

const LabelValueFmt string = "(" + qualifiedNameFmt + ")?"
const labelValueFmt string = "(" + qualifiedNameFmt + ")?"
const LabelValueMaxLength int = 63

var labelValueRegexp = regexp.MustCompile("^" + LabelValueFmt + "$")
var labelValueMaxLengthString = strconv.Itoa(LabelValueMaxLength)
var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")

func IsValidLabelValue(value string) bool {
return (len(value) <= LabelValueMaxLength && labelValueRegexp.MatchString(value))
// IsValidLabelValue tests whether the value passed is a valid label value. If
// 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])?"
Expand Down
6 changes: 3 additions & 3 deletions pkg/util/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ func TestIsValidLabelValue(t *testing.T) {
"", // empty value
}
for i := range successCases {
if !IsValidLabelValue(successCases[i]) {
t.Errorf("case %s expected success", successCases[i])
if errs := IsValidLabelValue(successCases[i]); len(errs) != 0 {
t.Errorf("case %s expected success: %v", successCases[i], errs)
}
}

Expand All @@ -273,7 +273,7 @@ func TestIsValidLabelValue(t *testing.T) {
strings.Repeat("a", 64), // over the limit
}
for i := range errorCases {
if IsValidLabelValue(errorCases[i]) {
if errs := IsValidLabelValue(errorCases[i]); len(errs) == 0 {
t.Errorf("case[%d] expected failure", i)
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/volume/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost)
allErrs := []error{}
for _, plugin := range plugins {
name := plugin.Name()
if len(validation.IsQualifiedName(name)) != 0 {
allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %#v", plugin))
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
continue
}

Expand Down
4 changes: 2 additions & 2 deletions plugin/pkg/scheduler/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ func (f *ConfigFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String,

failureDomainArgs := strings.Split(f.FailureDomains, ",")
for _, failureDomain := range failureDomainArgs {
if len(utilvalidation.IsQualifiedName(failureDomain)) != 0 {
return nil, fmt.Errorf("invalid failure domain: %s", failureDomain)
if errs := utilvalidation.IsQualifiedName(failureDomain); len(errs) != 0 {
return nil, fmt.Errorf("invalid failure domain: %q: %s", failureDomain, strings.Join(errs, ";"))
}
}

Expand Down