mirror of
https://github.com/rancher/os.git
synced 2025-09-01 14:48:55 +00:00
Bump libcompose and its dependencies
This commit is contained in:
4
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
4
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
@@ -3,10 +3,10 @@
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
// reference := repository [ ":" tag ] [ "@" digest ]
|
||||
// reference := name [ ":" tag ] [ "@" digest ]
|
||||
// name := [hostname '/'] component ['/' component]*
|
||||
// hostname := hostcomponent ['.' hostcomponent]* [':' port-number]
|
||||
// hostcomponent := /([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])/
|
||||
// hostcomponent := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// port-number := /[0-9]+/
|
||||
// component := alpha-numeric [separator alpha-numeric]*
|
||||
// alpha-numeric := /[a-z0-9]+/
|
||||
|
535
vendor/github.com/docker/distribution/reference/reference_test.go
generated
vendored
535
vendor/github.com/docker/distribution/reference/reference_test.go
generated
vendored
@@ -1,535 +0,0 @@
|
||||
package reference
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/distribution/digest"
|
||||
)
|
||||
|
||||
func TestReferenceParse(t *testing.T) {
|
||||
// referenceTestcases is a unified set of testcases for
|
||||
// testing the parsing of references
|
||||
referenceTestcases := []struct {
|
||||
// input is the repository name or name component testcase
|
||||
input string
|
||||
// err is the error expected from Parse, or nil
|
||||
err error
|
||||
// repository is the string representation for the reference
|
||||
repository string
|
||||
// hostname is the hostname expected in the reference
|
||||
hostname string
|
||||
// tag is the tag for the reference
|
||||
tag string
|
||||
// digest is the digest for the reference (enforces digest reference)
|
||||
digest string
|
||||
}{
|
||||
{
|
||||
input: "test_com",
|
||||
repository: "test_com",
|
||||
},
|
||||
{
|
||||
input: "test.com:tag",
|
||||
repository: "test.com",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test.com:5000",
|
||||
repository: "test.com",
|
||||
tag: "5000",
|
||||
},
|
||||
{
|
||||
input: "test.com/repo:tag",
|
||||
hostname: "test.com",
|
||||
repository: "test.com/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo",
|
||||
hostname: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo:tag",
|
||||
hostname: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
hostname: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
hostname: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
tag: "tag",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo",
|
||||
hostname: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
input: ":justtag",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "repo@sha256:ffffffffffffffffffffffffffffffffff",
|
||||
err: digest.ErrDigestInvalidLength,
|
||||
},
|
||||
{
|
||||
input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: digest.ErrDigestUnsupported,
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a:tag",
|
||||
err: ErrNameTooLong,
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 127) + "a:tag-puts-this-over-max",
|
||||
hostname: "a",
|
||||
repository: strings.Repeat("a/", 127) + "a",
|
||||
tag: "tag-puts-this-over-max",
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux",
|
||||
hostname: "sub-dom1.foo.com",
|
||||
repository: "sub-dom1.foo.com/bar/baz/quux",
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux:some-long-tag",
|
||||
hostname: "sub-dom1.foo.com",
|
||||
repository: "sub-dom1.foo.com/bar/baz/quux",
|
||||
tag: "some-long-tag",
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app:test.example.com",
|
||||
hostname: "b.gcr.io",
|
||||
repository: "b.gcr.io/test.example.com/my-app",
|
||||
tag: "test.example.com",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode
|
||||
hostname: "xn--n3h.com",
|
||||
repository: "xn--n3h.com/myimage",
|
||||
tag: "xn--n3h.com",
|
||||
},
|
||||
{
|
||||
input: "xn--7o8h.com/myimage:xn--7o8h.com@sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // 🐳.com in punycode
|
||||
hostname: "xn--7o8h.com",
|
||||
repository: "xn--7o8h.com/myimage",
|
||||
tag: "xn--7o8h.com",
|
||||
digest: "sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080",
|
||||
repository: "foo_bar.com",
|
||||
tag: "8080",
|
||||
},
|
||||
{
|
||||
input: "foo/foo_bar.com:8080",
|
||||
hostname: "foo",
|
||||
repository: "foo/foo_bar.com",
|
||||
tag: "8080",
|
||||
},
|
||||
}
|
||||
for _, testcase := range referenceTestcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
repo, err := Parse(testcase.input)
|
||||
if testcase.err != nil {
|
||||
if err == nil {
|
||||
failf("missing expected error: %v", testcase.err)
|
||||
} else if testcase.err != err {
|
||||
failf("mismatched error: got %v, expected %v", err, testcase.err)
|
||||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
failf("unexpected parse error: %v", err)
|
||||
continue
|
||||
}
|
||||
if repo.String() != testcase.input {
|
||||
failf("mismatched repo: got %q, expected %q", repo.String(), testcase.input)
|
||||
}
|
||||
|
||||
if named, ok := repo.(Named); ok {
|
||||
if named.Name() != testcase.repository {
|
||||
failf("unexpected repository: got %q, expected %q", named.Name(), testcase.repository)
|
||||
}
|
||||
hostname, _ := SplitHostname(named)
|
||||
if hostname != testcase.hostname {
|
||||
failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname)
|
||||
}
|
||||
} else if testcase.repository != "" || testcase.hostname != "" {
|
||||
failf("expected named type, got %T", repo)
|
||||
}
|
||||
|
||||
tagged, ok := repo.(Tagged)
|
||||
if testcase.tag != "" {
|
||||
if ok {
|
||||
if tagged.Tag() != testcase.tag {
|
||||
failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag)
|
||||
}
|
||||
} else {
|
||||
failf("expected tagged type, got %T", repo)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected tagged type")
|
||||
}
|
||||
|
||||
digested, ok := repo.(Digested)
|
||||
if testcase.digest != "" {
|
||||
if ok {
|
||||
if digested.Digest().String() != testcase.digest {
|
||||
failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest)
|
||||
}
|
||||
} else {
|
||||
failf("expected digested type, got %T", repo)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected digested type")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TestWithNameFailure tests cases where WithName should fail. Cases where it
|
||||
// should succeed are covered by TestSplitHostname, below.
|
||||
func TestWithNameFailure(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
input: "",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
input: ":justtag",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a:tag",
|
||||
err: ErrNameTooLong,
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
_, err := WithName(testcase.input)
|
||||
if err == nil {
|
||||
failf("no error parsing name. expected: %s", testcase.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitHostname(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
hostname string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
input: "test.com/foo",
|
||||
hostname: "test.com",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test_com/foo",
|
||||
hostname: "",
|
||||
name: "test_com/foo",
|
||||
},
|
||||
{
|
||||
input: "test:8080/foo",
|
||||
hostname: "test:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test.com:8080/foo",
|
||||
hostname: "test.com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test-com:8080/foo",
|
||||
hostname: "test-com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com:18080/foo",
|
||||
hostname: "xn--n3h.com:18080",
|
||||
name: "foo",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.input)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
hostname, name := SplitHostname(named)
|
||||
if hostname != testcase.hostname {
|
||||
failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname)
|
||||
}
|
||||
if name != testcase.name {
|
||||
failf("unexpected name: got %q, expected %q", name, testcase.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serializationType struct {
|
||||
Description string
|
||||
Field Field
|
||||
}
|
||||
|
||||
func TestSerialization(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
input string
|
||||
name string
|
||||
tag string
|
||||
digest string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
description: "empty value",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
description: "just a name",
|
||||
input: "example.com:8000/named",
|
||||
name: "example.com:8000/named",
|
||||
},
|
||||
{
|
||||
description: "name with a tag",
|
||||
input: "example.com:8000/named:tagged",
|
||||
name: "example.com:8000/named",
|
||||
tag: "tagged",
|
||||
},
|
||||
{
|
||||
description: "name with digest",
|
||||
input: "other.com/named@sha256:1234567890098765432112345667890098765432112345667890098765432112",
|
||||
name: "other.com/named",
|
||||
digest: "sha256:1234567890098765432112345667890098765432112345667890098765432112",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
m := map[string]string{
|
||||
"Description": testcase.description,
|
||||
"Field": testcase.input,
|
||||
}
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
failf("error marshalling: %v", err)
|
||||
}
|
||||
t := serializationType{}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
if testcase.err == nil {
|
||||
failf("error unmarshalling: %v", err)
|
||||
}
|
||||
if err != testcase.err {
|
||||
failf("wrong error, expected %v, got %v", testcase.err, err)
|
||||
}
|
||||
|
||||
continue
|
||||
} else if testcase.err != nil {
|
||||
failf("expected error unmarshalling: %v", testcase.err)
|
||||
}
|
||||
|
||||
if t.Description != testcase.description {
|
||||
failf("wrong description, expected %q, got %q", testcase.description, t.Description)
|
||||
}
|
||||
|
||||
ref := t.Field.Reference()
|
||||
|
||||
if named, ok := ref.(Named); ok {
|
||||
if named.Name() != testcase.name {
|
||||
failf("unexpected repository: got %q, expected %q", named.Name(), testcase.name)
|
||||
}
|
||||
} else if testcase.name != "" {
|
||||
failf("expected named type, got %T", ref)
|
||||
}
|
||||
|
||||
tagged, ok := ref.(Tagged)
|
||||
if testcase.tag != "" {
|
||||
if ok {
|
||||
if tagged.Tag() != testcase.tag {
|
||||
failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag)
|
||||
}
|
||||
} else {
|
||||
failf("expected tagged type, got %T", ref)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected tagged type")
|
||||
}
|
||||
|
||||
digested, ok := ref.(Digested)
|
||||
if testcase.digest != "" {
|
||||
if ok {
|
||||
if digested.Digest().String() != testcase.digest {
|
||||
failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest)
|
||||
}
|
||||
} else {
|
||||
failf("expected digested type, got %T", ref)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected digested type")
|
||||
}
|
||||
|
||||
t = serializationType{
|
||||
Description: testcase.description,
|
||||
Field: AsField(ref),
|
||||
}
|
||||
|
||||
b2, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
failf("error marshing serialization type: %v", err)
|
||||
}
|
||||
|
||||
if string(b) != string(b2) {
|
||||
failf("unexpected serialized value: expected %q, got %q", string(b), string(b2))
|
||||
}
|
||||
|
||||
// Ensure t.Field is not implementing "Reference" directly, getting
|
||||
// around the Reference type system
|
||||
var fieldInterface interface{} = t.Field
|
||||
if _, ok := fieldInterface.(Reference); ok {
|
||||
failf("field should not implement Reference interface")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithTag(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
tag string
|
||||
combined string
|
||||
}{
|
||||
{
|
||||
name: "test.com/foo",
|
||||
tag: "tag",
|
||||
combined: "test.com/foo:tag",
|
||||
},
|
||||
{
|
||||
name: "foo",
|
||||
tag: "tag2",
|
||||
combined: "foo:tag2",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
tag: "tag4",
|
||||
combined: "test.com:8000/foo:tag4",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
tag: "TAG5",
|
||||
combined: "test.com:8000/foo:TAG5",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.name)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.name)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
tagged, err := WithTag(named, testcase.tag)
|
||||
if err != nil {
|
||||
failf("WithTag failed: %s", err)
|
||||
}
|
||||
if tagged.String() != testcase.combined {
|
||||
failf("unexpected: got %q, expected %q", tagged.String(), testcase.combined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithDigest(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
digest digest.Digest
|
||||
combined string
|
||||
}{
|
||||
{
|
||||
name: "test.com/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "test.com/foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
{
|
||||
name: "foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "test.com:8000/foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.name)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.name)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
digested, err := WithDigest(named, testcase.digest)
|
||||
if err != nil {
|
||||
failf("WithDigest failed: %s", err)
|
||||
}
|
||||
if digested.String() != testcase.combined {
|
||||
failf("unexpected: got %q, expected %q", digested.String(), testcase.combined)
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/github.com/docker/distribution/reference/regexp.go
generated
vendored
4
vendor/github.com/docker/distribution/reference/regexp.go
generated
vendored
@@ -22,7 +22,7 @@ var (
|
||||
// hostnameComponentRegexp restricts the registry hostname component of a
|
||||
// repository name to start with a component as defined by hostnameRegexp
|
||||
// and followed by an optional port.
|
||||
hostnameComponentRegexp = match(`(?:[a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])`)
|
||||
hostnameComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
||||
|
||||
// hostnameRegexp defines the structure of potential hostname components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
@@ -49,7 +49,7 @@ var (
|
||||
|
||||
// NameRegexp is the format for the name component of references. The
|
||||
// regexp has capturing groups for the hostname and name part omitting
|
||||
// the seperating forward slash from either.
|
||||
// the separating forward slash from either.
|
||||
NameRegexp = expression(
|
||||
optional(hostnameRegexp, literal(`/`)),
|
||||
nameComponentRegexp,
|
||||
|
477
vendor/github.com/docker/distribution/reference/regexp_test.go
generated
vendored
477
vendor/github.com/docker/distribution/reference/regexp_test.go
generated
vendored
@@ -1,477 +0,0 @@
|
||||
package reference
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type regexpMatch struct {
|
||||
input string
|
||||
match bool
|
||||
subs []string
|
||||
}
|
||||
|
||||
func checkRegexp(t *testing.T, r *regexp.Regexp, m regexpMatch) {
|
||||
matches := r.FindStringSubmatch(m.input)
|
||||
if m.match && matches != nil {
|
||||
if len(matches) != (r.NumSubexp()+1) || matches[0] != m.input {
|
||||
t.Fatalf("Bad match result %#v for %q", matches, m.input)
|
||||
}
|
||||
if len(matches) < (len(m.subs) + 1) {
|
||||
t.Errorf("Expected %d sub matches, only have %d for %q", len(m.subs), len(matches)-1, m.input)
|
||||
}
|
||||
for i := range m.subs {
|
||||
if m.subs[i] != matches[i+1] {
|
||||
t.Errorf("Unexpected submatch %d: %q, expected %q for %q", i+1, matches[i+1], m.subs[i], m.input)
|
||||
}
|
||||
}
|
||||
} else if m.match {
|
||||
t.Errorf("Expected match for %q", m.input)
|
||||
} else if matches != nil {
|
||||
t.Errorf("Unexpected match for %q", m.input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostRegexp(t *testing.T) {
|
||||
hostcases := []regexpMatch{
|
||||
{
|
||||
input: "test.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "test.com:10304",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "test.com:http",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "localhost",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "localhost:8080",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a.b",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "ab.cd.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a-b.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "-ab.com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab-.com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab.c-om",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "ab.-com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab.com-",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "0101.com",
|
||||
match: true, // TODO(dmcgowan): valid if this should be allowed
|
||||
},
|
||||
{
|
||||
input: "001a.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "b.gbc.io:443",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "b.gbc.io",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com", // ☃.com in punycode
|
||||
match: true,
|
||||
},
|
||||
}
|
||||
r := regexp.MustCompile(`^` + hostnameRegexp.String() + `$`)
|
||||
for i := range hostcases {
|
||||
checkRegexp(t, r, hostcases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFullNameRegexp(t *testing.T) {
|
||||
if anchoredNameRegexp.NumSubexp() != 2 {
|
||||
t.Fatalf("anchored name regexp should have two submatches: %v, %v != 2",
|
||||
anchoredNameRegexp, anchoredNameRegexp.NumSubexp())
|
||||
}
|
||||
|
||||
testcases := []regexpMatch{
|
||||
{
|
||||
input: "",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "short",
|
||||
match: true,
|
||||
subs: []string{"", "short"},
|
||||
},
|
||||
{
|
||||
input: "simple/name",
|
||||
match: true,
|
||||
subs: []string{"simple", "name"},
|
||||
},
|
||||
{
|
||||
input: "library/ubuntu",
|
||||
match: true,
|
||||
subs: []string{"library", "ubuntu"},
|
||||
},
|
||||
{
|
||||
input: "docker/stevvooe/app",
|
||||
match: true,
|
||||
subs: []string{"docker", "stevvooe/app"},
|
||||
},
|
||||
{
|
||||
input: "aa/aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb",
|
||||
match: true,
|
||||
subs: []string{"aa", "aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb"},
|
||||
},
|
||||
{
|
||||
input: "aa/aa/bb/bb/bb",
|
||||
match: true,
|
||||
subs: []string{"aa", "aa/bb/bb/bb"},
|
||||
},
|
||||
{
|
||||
input: "a/a/a/a",
|
||||
match: true,
|
||||
subs: []string{"a", "a/a/a"},
|
||||
},
|
||||
{
|
||||
input: "a/a/a/a/",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "a//a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "a",
|
||||
match: true,
|
||||
subs: []string{"", "a"},
|
||||
},
|
||||
{
|
||||
input: "a/aa",
|
||||
match: true,
|
||||
subs: []string{"a", "aa"},
|
||||
},
|
||||
{
|
||||
input: "a/aa/a",
|
||||
match: true,
|
||||
subs: []string{"a", "aa/a"},
|
||||
},
|
||||
{
|
||||
input: "foo.com",
|
||||
match: true,
|
||||
subs: []string{"", "foo.com"},
|
||||
},
|
||||
{
|
||||
input: "foo.com/",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com:8080/bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com:8080", "bar"},
|
||||
},
|
||||
{
|
||||
input: "foo.com:http/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "bar"},
|
||||
},
|
||||
{
|
||||
input: "foo.com/bar/baz",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "bar/baz"},
|
||||
},
|
||||
{
|
||||
input: "localhost:8080/bar",
|
||||
match: true,
|
||||
subs: []string{"localhost:8080", "bar"},
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux",
|
||||
match: true,
|
||||
subs: []string{"sub-dom1.foo.com", "bar/baz/quux"},
|
||||
},
|
||||
{
|
||||
input: "blog.foo.com/bar/baz",
|
||||
match: true,
|
||||
subs: []string{"blog.foo.com", "bar/baz"},
|
||||
},
|
||||
{
|
||||
input: "a^a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "asdf$$^/aa",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "aa-a/a",
|
||||
match: true,
|
||||
subs: []string{"aa-a", "a"},
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a",
|
||||
match: true,
|
||||
subs: []string{"a", strings.Repeat("a/", 127) + "a"},
|
||||
},
|
||||
{
|
||||
input: "a-/a/a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/a-/a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "-foo/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo/bar-",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo-/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo/-bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "_foo/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo_bar",
|
||||
match: true,
|
||||
subs: []string{"", "foo_bar"},
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com",
|
||||
match: true,
|
||||
subs: []string{"", "foo_bar.com"},
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080/app",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/foo_bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "foo_bar"},
|
||||
},
|
||||
{
|
||||
input: "____/____",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "_docker/_docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker_/docker_",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app",
|
||||
match: true,
|
||||
subs: []string{"b.gcr.io", "test.example.com/my-app"},
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com/myimage", // ☃.com in punycode
|
||||
match: true,
|
||||
subs: []string{"xn--n3h.com", "myimage"},
|
||||
},
|
||||
{
|
||||
input: "xn--7o8h.com/myimage", // 🐳.com in punycode
|
||||
match: true,
|
||||
subs: []string{"xn--7o8h.com", "myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/xn--7o8h.com/myimage", // 🐳.com in punycode
|
||||
match: true,
|
||||
subs: []string{"example.com", "xn--7o8h.com/myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/some_separator__underscore/myimage",
|
||||
match: true,
|
||||
subs: []string{"example.com", "some_separator__underscore/myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/__underscore/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/.dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/nodouble..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/nodouble..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker./docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: ".docker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker-/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "-docker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do..cker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do__cker:8080/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do__cker/docker",
|
||||
match: true,
|
||||
subs: []string{"", "do__cker/docker"},
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app",
|
||||
match: true,
|
||||
subs: []string{"b.gcr.io", "test.example.com/my-app"},
|
||||
},
|
||||
{
|
||||
input: "registry.io/foo/project--id.module--name.ver---sion--name",
|
||||
match: true,
|
||||
subs: []string{"registry.io", "foo/project--id.module--name.ver---sion--name"},
|
||||
},
|
||||
}
|
||||
for i := range testcases {
|
||||
checkRegexp(t, anchoredNameRegexp, testcases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferenceRegexp(t *testing.T) {
|
||||
if ReferenceRegexp.NumSubexp() != 3 {
|
||||
t.Fatalf("anchored name regexp should have three submatches: %v, %v != 3",
|
||||
ReferenceRegexp, ReferenceRegexp.NumSubexp())
|
||||
}
|
||||
|
||||
testcases := []regexpMatch{
|
||||
{
|
||||
input: "registry.com:8080/myapp:tag",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "tag", ""},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp:tag2@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "tag2", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@sha256:badbadbadbad",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp:invalid~tag",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "bad_hostname.com:8080/myapp:tag",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input:// localhost treated as name, missing tag with 8080 as tag
|
||||
"localhost:8080@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost", "8080", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "localhost:8080/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost:8080/name", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "localhost:http/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
// localhost will be treated as an image name without a host
|
||||
input: "localhost@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@bad",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@2bad",
|
||||
match: false, // TODO(dmcgowan): Support this as valid
|
||||
},
|
||||
}
|
||||
|
||||
for i := range testcases {
|
||||
checkRegexp(t, ReferenceRegexp, testcases[i])
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user