Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions ociref/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func IsValidDigest(d string) bool {
// Unlike "docker pull" however, there is no default registry: when
// presented with a bare repository name, Parse will return an error.
func Parse(refStr string) (Reference, error) {
ref, err := ParseRelative(refStr)
ref, err := parse(refStr)
if err != nil {
return Reference{}, err
}
Expand All @@ -179,9 +179,28 @@ func Parse(refStr string) (Reference, error) {
//
// It is represented in string form as [HOST[:PORT]/]NAME[:TAG|@DIGEST]
// form: the same syntax accepted by "docker pull".
// Unlike "docker pull" however, there is no default registry: when
// presented with a bare repository name, the Host field will be empty.
// Like "docker pull", references without a host default to Docker Hub,
// and single-component Docker Hub repository names default to the "library"
// namespace.
func ParseRelative(refStr string) (Reference, error) {
ref, err := parse(refStr)
if err != nil {
return Reference{}, err
}
// Normalize Docker Hub registry hosts, also default to Docker if none is provided
if _, ok := ocidocker.DockerHubHosts[ref.Host]; ok || ref.Host == "" {
ref.Host = "docker.io"
}
if ref.Host == "docker.io" && !strings.Contains(ref.Repository, "/") {
ref.Repository = "library/" + ref.Repository
}
if len(ref.Repository) > 255 {
return Reference{}, fmt.Errorf("repository name too long")
}
return ref, nil
}

func parse(refStr string) (Reference, error) {
m := referencePat().FindStringSubmatch(refStr)
if m == nil {
return Reference{}, fmt.Errorf("invalid reference syntax (%q)", refStr)
Expand All @@ -201,13 +220,6 @@ func ParseRelative(refStr string) (Reference, error) {
return Reference{}, fmt.Errorf("invalid digest %q: %v", ref.Digest, err)
}
}
// Normalize Docker Hub registry hosts, also default to Docker if none is provided
if _, ok := ocidocker.DockerHubHosts[ref.Host]; ok || ref.Host == "" {
ref.Host = "docker.io"
}
if ref.Host == "docker.io" && !strings.Contains(ref.Repository, "/") {
ref.Repository = "library/" + ref.Repository
}
if len(ref.Repository) > 255 {
return Reference{}, fmt.Errorf("repository name too long")
}
Expand Down
59 changes: 52 additions & 7 deletions ociref/reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,15 +400,60 @@ func TestParseReference(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, test.wantRef, ref)
//assert.Equal(t, test.input, ref.String())
if test.wantRef.Host != "" {
ref1, err := Parse(test.input)
require.NoError(t, err)
assert.Equal(t, test.wantRef, ref1)
} else {
_, err := Parse(test.input)
})
}
}

func TestParse(t *testing.T) {
tests := []struct {
input string
wantErr string
wantRef Reference
}{{
input: "test.com/repo:tag",
wantRef: Reference{
Host: "test.com",
Repository: "repo",
Tag: "tag",
},
}, {
input: "test:5000/repo",
wantRef: Reference{
Host: "test:5000",
Repository: "repo",
},
}, {
input: "docker.io/ubuntu",
wantRef: Reference{
Host: "docker.io",
Repository: "ubuntu",
},
}, {
input: "index.docker.io/foo",
wantRef: Reference{
Host: "index.docker.io",
Repository: "foo",
},
}, {
input: "test_com",
wantErr: `reference does not contain host name`,
}, {
input: "rocket.chat",
wantErr: `reference does not contain host name`,
}, {
input: "test.com:5000",
wantErr: `reference does not contain host name`,
}}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
ref, err := Parse(test.input)
if test.wantErr != "" {
require.Error(t, err)
require.Regexp(t, `reference does not contain host name`, err.Error())
require.Regexp(t, test.wantErr, err.Error())
return
}
require.NoError(t, err)
assert.Equal(t, test.wantRef, ref)
})
}
}
Expand Down
Loading