forked from TrueCloudLab/distribution
Update ParseNamed to require canonical form
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
parent
954b4e8154
commit
6170ac53da
3 changed files with 89 additions and 6 deletions
|
@ -208,6 +208,13 @@ func TestParseRepositoryInfo(t *testing.T) {
|
||||||
AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
|
AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
|
||||||
Domain: "docker.io",
|
Domain: "docker.io",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
RemoteName: "library/foo",
|
||||||
|
FamiliarName: "foo",
|
||||||
|
FullName: "docker.io/library/foo",
|
||||||
|
AmbiguousName: "docker.io/foo",
|
||||||
|
Domain: "docker.io",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
RemoteName: "library/foo/bar",
|
RemoteName: "library/foo/bar",
|
||||||
FamiliarName: "library/foo/bar",
|
FamiliarName: "library/foo/bar",
|
||||||
|
|
|
@ -55,6 +55,9 @@ var (
|
||||||
|
|
||||||
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
|
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
|
||||||
ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
|
ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
|
||||||
|
|
||||||
|
// ErrNameNotCanonical is returned when a name is not canonical.
|
||||||
|
ErrNameNotCanonical = errors.New("repository name must be canonical")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reference is an opaque object reference identifier that may include
|
// Reference is an opaque object reference identifier that may include
|
||||||
|
@ -231,18 +234,17 @@ func Parse(s string) (Reference, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseNamed parses s and returns a syntactically valid reference implementing
|
// ParseNamed parses s and returns a syntactically valid reference implementing
|
||||||
// the Named interface. The reference must have a name, otherwise an error is
|
// the Named interface. The reference must have a name and be in the canonical
|
||||||
// returned.
|
// form, otherwise an error is returned.
|
||||||
// If an error was encountered it is returned, along with a nil Reference.
|
// If an error was encountered it is returned, along with a nil Reference.
|
||||||
// NOTE: ParseNamed will not handle short digests.
|
// NOTE: ParseNamed will not handle short digests.
|
||||||
func ParseNamed(s string) (Named, error) {
|
func ParseNamed(s string) (Named, error) {
|
||||||
ref, err := Parse(s)
|
named, err := ParseNormalizedNamed(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
named, isNamed := ref.(Named)
|
if named.String() != s {
|
||||||
if !isNamed {
|
return nil, ErrNameNotCanonical
|
||||||
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
|
||||||
}
|
}
|
||||||
return named, nil
|
return named, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -583,3 +583,77 @@ func TestWithDigest(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseNamed(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
input string
|
||||||
|
domain string
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "test.com/foo",
|
||||||
|
domain: "test.com",
|
||||||
|
name: "foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "test:8080/foo",
|
||||||
|
domain: "test:8080",
|
||||||
|
name: "foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "test_com/foo",
|
||||||
|
err: ErrNameNotCanonical,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "test.com",
|
||||||
|
err: ErrNameNotCanonical,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "foo",
|
||||||
|
err: ErrNameNotCanonical,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "library/foo",
|
||||||
|
err: ErrNameNotCanonical,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "docker.io/library/foo",
|
||||||
|
domain: "docker.io",
|
||||||
|
name: "library/foo",
|
||||||
|
},
|
||||||
|
// Ambiguous case, parser will add "library/" to foo
|
||||||
|
{
|
||||||
|
input: "docker.io/foo",
|
||||||
|
err: ErrNameNotCanonical,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, testcase := range testcases {
|
||||||
|
failf := func(format string, v ...interface{}) {
|
||||||
|
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
named, err := ParseNamed(testcase.input)
|
||||||
|
if err != nil && testcase.err == nil {
|
||||||
|
failf("error parsing name: %s", err)
|
||||||
|
continue
|
||||||
|
} else if err == nil && testcase.err != nil {
|
||||||
|
failf("parsing succeded: expected error %v", testcase.err)
|
||||||
|
continue
|
||||||
|
} else if err != testcase.err {
|
||||||
|
failf("unexpected error %v, expected %v", err, testcase.err)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
domain, name := SplitHostname(named)
|
||||||
|
if domain != testcase.domain {
|
||||||
|
failf("unexpected domain: got %q, expected %q", domain, testcase.domain)
|
||||||
|
}
|
||||||
|
if name != testcase.name {
|
||||||
|
failf("unexpected name: got %q, expected %q", name, testcase.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue