From 71d375e22f628bf21551d04890bc3282d2cb19cb Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Wed, 13 May 2015 16:28:48 -0700 Subject: [PATCH] Add test case for qname validation, fix impl --- docs/resources.md | 8 ++++---- pkg/util/validation.go | 15 ++++++++------- pkg/util/validation_test.go | 2 ++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/resources.md b/docs/resources.md index 2566f0d99e1..d4241cd30b2 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -21,12 +21,12 @@ Note that the resource model currently prohibits over-committing resources; we w All resources have a _type_ that is identified by their _typename_ (a string, e.g., "memory"). Several resource types are predefined by Kubernetes (a full list is below), although only two will be supported at first: CPU and memory. Users and system administrators can define their own resource types if they wish (e.g., Hadoop slots). -A fully-qualified resource typename is constructed from a DNS-style _subdomain_, followed by a slash `/`, followed by a DNS Label. -* The subdomain must conform to [RFC 1035](http://tools.ietf.org/html/rfc1035) / [RFC 1123](http://www.ietf.org/rfc/rfc1123.txt) (e.g., `kubernetes.io`, `myveryown.org`). -* The DNS label must conform to [RFC 1123](http://www.ietf.org/rfc/rfc1123.txt) - alphanumeric characters, with a maximum length of 63 characters, with the '-' character allowed anywhere except the first or last character. +A fully-qualified resource typename is constructed from a DNS-style _subdomain_, followed by a slash `/`, followed by a name. +* The subdomain must conform to [RFC 1123](http://www.ietf.org/rfc/rfc1123.txt) (e.g., `kubernetes.io`, `example.com`). +* The name must be not more than 63 characters, consisting of upper- or lower-case alphanumeric characters, with the `-`, `_`, and `.` characters allowed anywhere except the first or last character. * As a shorthand, any resource typename that does not start with a subdomain and a slash will automatically be prefixed with the built-in Kubernetes _namespace_, `kubernetes.io/` in order to fully-qualify it. This namespace is reserved for code in the open source Kubernetes repository; as a result, all user typenames MUST be fully qualified, and cannot be created in this namespace. -Some example typenames include `memory` (which will be fully-qualified as `kubernetes.io/memory`), and `myveryown.org/shiny-new-resource`. +Some example typenames include `memory` (which will be fully-qualified as `kubernetes.io/memory`), and `example.com/Shiny_New-Resource.Type`. For future reference, note that some resources, such as CPU and network bandwidth, are _compressible_, which means that their usage can potentially be throttled in a relatively benign manner. All other resources are _incompressible_, which means that any attempt to throttle them is likely to cause grief. This distinction will be important if a Kubernetes implementation supports over-committing of resources. diff --git a/pkg/util/validation.go b/pkg/util/validation.go index 7cd66227663..dd8905eb5da 100644 --- a/pkg/util/validation.go +++ b/pkg/util/validation.go @@ -31,20 +31,21 @@ var qualifiedNameRegexp = regexp.MustCompile("^" + QualifiedNameFmt + "$") func IsQualifiedName(value string) bool { parts := strings.Split(value, "/") - var left, right string + var name string switch len(parts) { case 1: - left, right = "", parts[0] + name = parts[0] case 2: - left, right = parts[0], parts[1] + var prefix string + prefix, name = parts[0], parts[1] + if prefix == "" || !IsDNS1123Subdomain(prefix) { + return false + } default: return false } - if left != "" && !IsDNS1123Subdomain(left) { - return false - } - return right != "" && len(right) <= QualifiedNameMaxLength && qualifiedNameRegexp.MatchString(right) + return name != "" && len(name) <= QualifiedNameMaxLength && qualifiedNameRegexp.MatchString(name) } const LabelValueFmt string = "(" + QualifiedNameFmt + ")?" diff --git a/pkg/util/validation_test.go b/pkg/util/validation_test.go index c5ad31cedf3..c29f2ddd26f 100644 --- a/pkg/util/validation_test.go +++ b/pkg/util/validation_test.go @@ -186,6 +186,8 @@ func TestIsQualifiedName(t *testing.T) { "only/one/slash", "Example.com/abc", "example_com/abc", + "example.com/", + "/simple", strings.Repeat("a", 64), strings.Repeat("a", 254) + "/abc", }