diff --git a/events/exchange/exchange.go b/events/exchange/exchange.go index 59273c952..eb27bf29b 100644 --- a/events/exchange/exchange.go +++ b/events/exchange/exchange.go @@ -225,7 +225,7 @@ func validateTopic(topic string) error { } func validateEnvelope(envelope *events.Envelope) error { - if err := namespaces.Validate(envelope.Namespace); err != nil { + if err := identifiers.Validate(envelope.Namespace); err != nil { return errors.Wrapf(err, "event envelope has invalid namespace") } diff --git a/metadata/namespaces.go b/metadata/namespaces.go index 25d0e1578..23615e48f 100644 --- a/metadata/namespaces.go +++ b/metadata/namespaces.go @@ -20,6 +20,7 @@ import ( "context" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/identifiers" l "github.com/containerd/containerd/labels" "github.com/containerd/containerd/namespaces" "github.com/pkg/errors" @@ -41,7 +42,7 @@ func (s *namespaceStore) Create(ctx context.Context, namespace string, labels ma return err } - if err := namespaces.Validate(namespace); err != nil { + if err := identifiers.Validate(namespace); err != nil { return err } diff --git a/namespaces/context.go b/namespaces/context.go index 20596f09d..b53c9012c 100644 --- a/namespaces/context.go +++ b/namespaces/context.go @@ -21,6 +21,7 @@ import ( "os" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/identifiers" "github.com/pkg/errors" ) @@ -70,7 +71,7 @@ func NamespaceRequired(ctx context.Context) (string, error) { if !ok || namespace == "" { return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required") } - if err := Validate(namespace); err != nil { + if err := identifiers.Validate(namespace); err != nil { return "", errors.Wrap(err, "namespace validation") } return namespace, nil diff --git a/namespaces/validate.go b/namespaces/validate.go deleted file mode 100644 index 222da3ea4..000000000 --- a/namespaces/validate.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// Package namespaces provides tools for working with namespaces across -// containerd. -// -// Namespaces collect resources such as containers and images, into a unique -// identifier space. This means that two applications can use the same -// identifiers and not conflict while using containerd. -// -// This package can be used to ensure that client and server functions -// correctly store the namespace on the context. -package namespaces - -import ( - "regexp" - - "github.com/containerd/containerd/errdefs" - "github.com/pkg/errors" -) - -const ( - maxLength = 76 - alpha = `[A-Za-z]` - alphanum = `[A-Za-z0-9]+` - label = alpha + alphanum + `(:?[-]+` + alpha + alphanum + `)*` -) - -var ( - // namespaceRe validates that a namespace matches valid identifiers. - // - // Rules for domains, defined in RFC 1035, section 2.3.1, are used for - // namespaces. - namespaceRe = regexp.MustCompile(reAnchor(label + reGroup("[.]"+reGroup(label)) + "*")) -) - -// Validate returns nil if the string s is a valid namespace. -// -// To allow such namespace identifiers to be used across various contexts -// safely, the character set has been restricted to that defined for domains in -// RFC 1035, section 2.3.1. This will make namespace identifiers safe for use -// across networks, filesystems and other media. -// -// The identifier specification departs from RFC 1035 in that it allows -// "labels" to start with number and only enforces a total length restriction -// of 76 characters. -// -// While the character set may be expanded in the future, namespace identifiers -// are guaranteed to be safely used as filesystem path components. -// -// For the most part, this doesn't need to be called directly when using the -// context-oriented functions. -func Validate(s string) error { - if len(s) > maxLength { - return errors.Wrapf(errdefs.ErrInvalidArgument, "namespace %q greater than maximum length (%d characters)", s, maxLength) - } - - if !namespaceRe.MatchString(s) { - return errors.Wrapf(errdefs.ErrInvalidArgument, "namespace %q must match %v", s, namespaceRe) - } - return nil -} - -func reGroup(s string) string { - return `(?:` + s + `)` -} - -func reAnchor(s string) string { - return `^` + s + `$` -} diff --git a/namespaces/validate_test.go b/namespaces/validate_test.go deleted file mode 100644 index af229218d..000000000 --- a/namespaces/validate_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package namespaces - -import ( - "strings" - "testing" - - "github.com/containerd/containerd/errdefs" -) - -func TestValidNamespaces(t *testing.T) { - for _, input := range []string{ - "default", - "Default", - t.Name(), - "default-default", - "default--default", - "containerd.io", - "foo.boo", - "swarmkit.docker.io", - "zn--e9.org", // or something like it! - strings.Repeat("a", maxLength), - } { - t.Run(input, func(t *testing.T) { - if err := Validate(input); err != nil { - t.Fatalf("unexpected error: %v != nil", err) - } - }) - } -} - -func TestInvalidNamespaces(t *testing.T) { - for _, input := range []string{ - ".foo..foo", - "foo/foo", - "foo/..", - "foo..foo", - "foo.-boo", - "foo.-boo.bar", - "-foo.boo", - "foo.boo-", - "foo_foo.boo_underscores", // boo-urns? - "0912341234", - "task.0.0123456789", - strings.Repeat("a", maxLength+1), - } { - - t.Run(input, func(t *testing.T) { - if err := Validate(input); err == nil { - t.Fatal("expected invalid error") - } else if !errdefs.IsInvalidArgument(err) { - t.Fatal("error should be an invalid identifier error") - } - }) - } -}