commit
4bf3547399
5 changed files with 181 additions and 7 deletions
|
@ -22,7 +22,14 @@ func TestValidateReferenceName(t *testing.T) {
|
|||
"127.0.0.1:5000/docker/docker",
|
||||
"127.0.0.1:5000/library/debian",
|
||||
"127.0.0.1:5000/debian",
|
||||
"192.168.0.1",
|
||||
"192.168.0.1:80",
|
||||
"192.168.0.1:8/debian",
|
||||
"192.168.0.2:25000/debian",
|
||||
"thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
|
||||
"[fc00::1]:5000/docker",
|
||||
"[fc00::1]:5000/docker/docker",
|
||||
"[fc00:1:2:3:4:5:6:7]:5000/library/debian",
|
||||
|
||||
// This test case was moved from invalid to valid since it is valid input
|
||||
// when specified with a hostname, it removes the ambiguity from about
|
||||
|
@ -40,6 +47,11 @@ func TestValidateReferenceName(t *testing.T) {
|
|||
"docker///docker",
|
||||
"docker.io/docker/Docker",
|
||||
"docker.io/docker///docker",
|
||||
"[fc00::1]",
|
||||
"[fc00::1]:5000",
|
||||
"fc00::1:5000/debian",
|
||||
"[fe80::1%eth0]:5000/debian",
|
||||
"[2001:db8:3:4::192.0.2.33]:5000/debian",
|
||||
"1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
//
|
||||
// reference := name [ ":" tag ] [ "@" digest ]
|
||||
// name := [domain '/'] path-component ['/' path-component]*
|
||||
// domain := domain-component ['.' domain-component]* [':' port-number]
|
||||
// domain := host [':' port-number]
|
||||
// host := domain-name | IPv4address | \[ IPv6address \] ; rfc3986 appendix-A
|
||||
// domain-name := domain-component ['.' domain-component]*
|
||||
// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// port-number := /[0-9]+/
|
||||
// path-component := alpha-numeric [separator alpha-numeric]*
|
||||
|
|
|
@ -171,6 +171,101 @@ func TestReferenceParse(t *testing.T) {
|
|||
repository: "foo/foo_bar.com",
|
||||
tag: "8080",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1",
|
||||
repository: "192.168.1.1",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:tag",
|
||||
repository: "192.168.1.1",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:5000",
|
||||
repository: "192.168.1.1",
|
||||
tag: "5000",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1/repo",
|
||||
domain: "192.168.1.1",
|
||||
repository: "192.168.1.1/repo",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:5000/repo",
|
||||
domain: "192.168.1.1:5000",
|
||||
repository: "192.168.1.1:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:5000/repo:5050",
|
||||
domain: "192.168.1.1:5000",
|
||||
repository: "192.168.1.1:5000/repo",
|
||||
tag: "5050",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:5000",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:tag",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]/repo",
|
||||
domain: "[2001:db8::1]",
|
||||
repository: "[2001:db8::1]/repo",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8:1:2:3:4:5:6]/repo:tag",
|
||||
domain: "[2001:db8:1:2:3:4:5:6]",
|
||||
repository: "[2001:db8:1:2:3:4:5:6]/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:5000/repo",
|
||||
domain: "[2001:db8::1]:5000",
|
||||
repository: "[2001:db8::1]:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:5000/repo:tag",
|
||||
domain: "[2001:db8::1]:5000",
|
||||
repository: "[2001:db8::1]:5000/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
domain: "[2001:db8::1]:5000",
|
||||
repository: "[2001:db8::1]:5000/repo",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::1]:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
domain: "[2001:db8::1]:5000",
|
||||
repository: "[2001:db8::1]:5000/repo",
|
||||
tag: "tag",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "[2001:db8::]:5000/repo",
|
||||
domain: "[2001:db8::]:5000",
|
||||
repository: "[2001:db8::]:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "[::1]:5000/repo",
|
||||
domain: "[::1]:5000",
|
||||
repository: "[::1]:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "[fe80::1%eth0]:5000/repo",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "[fe80::1%@invalidzone]:5000/repo",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
}
|
||||
for _, testcase := range referenceTestcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
|
|
|
@ -23,15 +23,40 @@ var (
|
|||
alphaNumeric,
|
||||
optional(repeated(separator, alphaNumeric)))
|
||||
|
||||
// domainComponent restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by DomainRegexp
|
||||
// and followed by an optional port.
|
||||
domainComponent = `(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`
|
||||
// domainNameComponent restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by DomainRegexp.
|
||||
domainNameComponent = `(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`
|
||||
|
||||
// ipv6address are enclosed between square brackets and may be represented
|
||||
// in many ways, see rfc5952. Only IPv6 in compressed or uncompressed format
|
||||
// are allowed, IPv6 zone identifiers (rfc6874) or Special addresses such as
|
||||
// IPv4-Mapped are deliberately excluded.
|
||||
ipv6address = expression(
|
||||
literal(`[`), `(?:[a-fA-F0-9:]+)`, literal(`]`),
|
||||
)
|
||||
|
||||
// domainName defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names. This includes IPv4 addresses on decimal format.
|
||||
domainName = expression(
|
||||
domainNameComponent,
|
||||
optional(repeated(literal(`.`), domainNameComponent)),
|
||||
)
|
||||
|
||||
// host defines the structure of potential domains based on the URI
|
||||
// Host subcomponent on rfc3986. It may be a subset of DNS domain name,
|
||||
// or an IPv4 address in decimal format, or an IPv6 address between square
|
||||
// brackets (excluding zone identifiers as defined by rfc6874 or special
|
||||
// addresses such as IPv4-Mapped).
|
||||
host = `(?:` + domainName + `|` + ipv6address + `)`
|
||||
|
||||
// allowed by the URI Host subcomponent on rfc3986 to ensure backwards
|
||||
// compatibility with Docker image names.
|
||||
domain = expression(
|
||||
domainComponent,
|
||||
optional(repeated(literal(`.`), domainComponent)),
|
||||
host,
|
||||
optional(literal(`:`), `[0-9]+`))
|
||||
|
||||
// DomainRegexp defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
|
|
|
@ -115,6 +115,46 @@ func TestDomainRegexp(t *testing.T) {
|
|||
input: "Asdf.com", // uppercase character
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:75050", // ipv4
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "192.168.1.1:750050", // port with more than 5 digits, it will fail on validation
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "[fd00:1:2::3]:75050", // ipv6 compressed
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "[fd00:1:2::3]75050", // ipv6 wrong port separator
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "[fd00:1:2::3]::75050", // ipv6 wrong port separator
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "[fd00:1:2::3%eth0]:75050", // ipv6 with zone
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "[fd00123123123]:75050", // ipv6 wrong format, will fail in validation
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:75050", // ipv6 long format
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:750505", // ipv6 long format and invalid port, it will fail in validation
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "fd00:1:2::3:75050", // bad ipv6 without square brackets
|
||||
match: false,
|
||||
},
|
||||
}
|
||||
r := regexp.MustCompile(`^` + DomainRegexp.String() + `$`)
|
||||
for i := range hostcases {
|
||||
|
|
Loading…
Reference in a new issue