Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace docker.io as the default registry with <local> #448

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion copy/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestCreateSignature(t *testing.T) {
assert.Error(t, err)

// Set up a docker: reference
dockerRef, err := docker.ParseReference("//busybox")
dockerRef, err := docker.ParseReference("//docker.io/library/busybox")
require.NoError(t, err)
dockerDest, err := dockerRef.NewImageDestination(context.Background(),
&types.SystemContext{RegistriesDirPath: "/this/doesnt/exist", DockerPerHostCertDirPath: "/this/doesnt/exist"})
Expand Down
8 changes: 4 additions & 4 deletions docker/archive/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ func testParseReference(t *testing.T, fn func(string) (types.ImageReference, err
for _, c := range []struct{ input, expectedPath, expectedRef string }{
{"", "", ""}, // Empty input is explicitly rejected
{"/path", "/path", ""},
{"/path:busybox:notlatest", "/path", "docker.io/library/busybox:notlatest"}, // Explicit tag
{"/path:busybox" + sha256digest, "", ""}, // Digest references are forbidden
{"/path:busybox", "/path", "docker.io/library/busybox:latest"}, // Default tag
{"/path:busybox:notlatest", "/path", "<local>/library/busybox:notlatest"}, // Explicit tag
{"/path:busybox" + sha256digest, "", ""}, // Digest references are forbidden
{"/path:busybox", "/path", "<local>/library/busybox:latest"}, // Default tag
// A github.com/distribution/reference value can have a tag and a digest at the same time!
{"/path:busybox:latest" + sha256digest, "", ""}, // Both tag and digest is rejected
{"/path:docker.io/library/busybox:latest", "/path", "docker.io/library/busybox:latest"}, // All implied values explicitly specified
Expand Down Expand Up @@ -86,7 +86,7 @@ func (ref refWithTagAndDigest) Tag() string {
// A common list of reference formats to test for the various ImageReference methods.
var validReferenceTestCases = []struct{ input, dockerRef, stringWithinTransport string }{
{"/pathonly", "", "/pathonly"},
{"/path:busybox:notlatest", "docker.io/library/busybox:notlatest", "/path:docker.io/library/busybox:notlatest"}, // Explicit tag
{"/path:busybox:notlatest", "<local>/library/busybox:notlatest", "/path:<local>/library/busybox:notlatest"}, // Explicit tag
{"/path:docker.io/library/busybox:latest", "docker.io/library/busybox:latest", "/path:docker.io/library/busybox:latest"}, // All implied values explicitly specified
{"/path:example.com/ns/foo:bar", "example.com/ns/foo:bar", "/path:example.com/ns/foo:bar"}, // All values explicitly specified
}
Expand Down
12 changes: 6 additions & 6 deletions docker/daemon/daemon_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func testParseReference(t *testing.T, fn func(string) (types.ImageReference, err
{"sha256:XX23456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "", ""}, // Invalid digest value
{"UPPERCASEISINVALID", "", ""}, // Invalid reference input
{"busybox", "", ""}, // Missing tag or digest
{"busybox:latest", "", "docker.io/library/busybox:latest"}, // Explicit tag
{"busybox@" + sha256digest, "", "docker.io/library/busybox@" + sha256digest}, // Explicit digest
{"busybox:latest", "", "<local>/library/busybox:latest"}, // Explicit tag
{"busybox@" + sha256digest, "", "<local>/library/busybox@" + sha256digest}, // Explicit digest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the long comment in docker/tarfile/Destination.PutManifest, this would break interoperability with projectatomic/docker.

// A github.com/distribution/reference value can have a tag and a digest at the same time!
// Most versions of docker/reference do not handle that (ignoring the tag), so we reject such input.
{"busybox:latest@" + sha256digest, "", ""}, // Both tag and digest
Expand Down Expand Up @@ -92,10 +92,10 @@ func testParseReference(t *testing.T, fn func(string) (types.ImageReference, err
// A common list of reference formats to test for the various ImageReference methods.
// (For IDs it is much simpler, we simply use them unmodified)
var validNamedReferenceTestCases = []struct{ input, dockerRef, stringWithinTransport string }{
{"busybox:notlatest", "docker.io/library/busybox:notlatest", "busybox:notlatest"}, // Explicit tag
{"busybox" + sha256digest, "docker.io/library/busybox" + sha256digest, "busybox" + sha256digest}, // Explicit digest
{"docker.io/library/busybox:latest", "docker.io/library/busybox:latest", "busybox:latest"}, // All implied values explicitly specified
{"example.com/ns/foo:bar", "example.com/ns/foo:bar", "example.com/ns/foo:bar"}, // All values explicitly specified
{"busybox:notlatest", "<local>/library/busybox:notlatest", "busybox:notlatest"}, // Explicit tag
{"busybox" + sha256digest, "<local>/library/busybox" + sha256digest, "busybox" + sha256digest}, // Explicit digest
{"<local>/library/busybox:latest", "<local>/library/busybox:latest", "busybox:latest"}, // All implied values explicitly specified
{"example.com/ns/foo:bar", "example.com/ns/foo:bar", "example.com/ns/foo:bar"}, // All values explicitly specified
}

func TestNewReference(t *testing.T) {
Expand Down
24 changes: 12 additions & 12 deletions docker/docker_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func TestParseReference(t *testing.T) {
func testParseReference(t *testing.T, fn func(string) (types.ImageReference, error)) {
for _, c := range []struct{ input, expected string }{
{"busybox", ""}, // Missing // prefix
{"//busybox:notlatest", "docker.io/library/busybox:notlatest"}, // Explicit tag
{"//busybox" + sha256digest, "docker.io/library/busybox" + sha256digest}, // Explicit digest
{"//busybox", "docker.io/library/busybox:latest"}, // Default tag
{"//busybox:notlatest", "<local>/library/busybox:notlatest"}, // Explicit tag
{"//busybox" + sha256digest, "<local>/library/busybox" + sha256digest}, // Explicit digest
{"//busybox", "<local>/library/busybox:latest"}, // Default tag
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still essentially breaks the world; skopeo inspect docker://busybox will no longer do anything useful.

// A github.com/distribution/reference value can have a tag and a digest at the same time!
// The docker/distribution API does not really support that (we can’t ask for an image with a specific
// tag and digest), so fail. This MAY be accepted in the future.
Expand All @@ -68,10 +68,10 @@ func testParseReference(t *testing.T, fn func(string) (types.ImageReference, err

// A common list of reference formats to test for the various ImageReference methods.
var validReferenceTestCases = []struct{ input, dockerRef, stringWithinTransport string }{
{"busybox:notlatest", "docker.io/library/busybox:notlatest", "//busybox:notlatest"}, // Explicit tag
{"busybox" + sha256digest, "docker.io/library/busybox" + sha256digest, "//busybox" + sha256digest}, // Explicit digest
{"docker.io/library/busybox:latest", "docker.io/library/busybox:latest", "//busybox:latest"}, // All implied values explicitly specified
{"example.com/ns/foo:bar", "example.com/ns/foo:bar", "//example.com/ns/foo:bar"}, // All values explicitly specified
{"busybox:notlatest", "<local>/library/busybox:notlatest", "//busybox:notlatest"}, // Explicit tag
{"busybox" + sha256digest, "<local>/library/busybox" + sha256digest, "//busybox" + sha256digest}, // Explicit digest
{"<local>/library/busybox1:latest", "<local>/library/busybox1:latest", "//busybox1:latest"}, // All implied values explicitly specified
{"example.com/ns/foo:bar", "example.com/ns/foo:bar", "//example.com/ns/foo:bar"}, // All values explicitly specified
}

func TestNewReference(t *testing.T) {
Expand Down Expand Up @@ -136,22 +136,22 @@ func TestReferencePolicyConfigurationIdentity(t *testing.T) {
// Just a smoke test, the substance is tested in policyconfiguration.TestDockerReference.
ref, err := ParseReference("//busybox")
require.NoError(t, err)
assert.Equal(t, "docker.io/library/busybox:latest", ref.PolicyConfigurationIdentity())
assert.Equal(t, "<local>/library/busybox:latest", ref.PolicyConfigurationIdentity())
}

func TestReferencePolicyConfigurationNamespaces(t *testing.T) {
// Just a smoke test, the substance is tested in policyconfiguration.TestDockerReference.
ref, err := ParseReference("//busybox")
require.NoError(t, err)
assert.Equal(t, []string{
"docker.io/library/busybox",
"docker.io/library",
"docker.io",
"<local>/library/busybox",
"<local>/library",
"<local>",
}, ref.PolicyConfigurationNamespaces())
}

func TestReferenceNewImage(t *testing.T) {
ref, err := ParseReference("//busybox")
ref, err := ParseReference("//docker.io/library/busybox")
require.NoError(t, err)
img, err := ref.NewImage(context.Background(), &types.SystemContext{
RegistriesDirPath: "/this/doesnt/exist",
Expand Down
10 changes: 5 additions & 5 deletions docker/policyconfiguration/naming_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ func TestDockerReference(t *testing.T) {
"localhost/ns/repo": {"localhost/ns/repo", "localhost/ns", "localhost"},
// Note that "localhost" is special here: notlocalhost/repo is parsed as docker.io/notlocalhost.repo:
"localhost/repo": {"localhost/repo", "localhost"},
"notlocalhost/repo": {"docker.io/notlocalhost/repo", "docker.io/notlocalhost", "docker.io"},
"notlocalhost/repo": {"<local>/notlocalhost/repo", "<local>/notlocalhost", "<local>"},
"docker.io/ns/repo": {"docker.io/ns/repo", "docker.io/ns", "docker.io"},
"docker.io/library/repo": {"docker.io/library/repo", "docker.io/library", "docker.io"},
"docker.io/repo": {"docker.io/library/repo", "docker.io/library", "docker.io"},
"ns/repo": {"docker.io/ns/repo", "docker.io/ns", "docker.io"},
"library/repo": {"docker.io/library/repo", "docker.io/library", "docker.io"},
"repo": {"docker.io/library/repo", "docker.io/library", "docker.io"},
"<local>/repo": {"<local>/library/repo", "<local>/library", "<local>"},
"ns/repo": {"<local>/ns/repo", "<local>/ns", "<local>"},
"library/repo": {"<local>/library/repo", "<local>/library", "<local>"},
"repo": {"<local>/library/repo", "<local>/library", "<local>"},
} {
for inputSuffix, mappedSuffix := range map[string]string{
":tag": ":tag",
Expand Down
21 changes: 10 additions & 11 deletions docker/reference/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ import (
)

var (
legacyDefaultDomain = "index.docker.io"
defaultDomain = "docker.io"
officialRepoName = "library"
defaultTag = "latest"
defaultDomain = "<local>"
officialRepoName = "library"
defaultTag = "latest"
)

// normalizedNamed represents a name which has been
// normalized and has a familiar form. A familiar name
// is what is used in Docker UI. An example normalized
// name is "docker.io/library/ubuntu" and corresponding
// name is "<local>/library/ubuntu" and corresponding
// familiar name of "ubuntu".
type normalizedNamed interface {
Named
Expand Down Expand Up @@ -60,13 +59,13 @@ func ParseNormalizedNamed(s string) (Named, error) {
// needs to be already validated before.
func splitDockerDomain(name string) (domain, remainder string) {
i := strings.IndexRune(name, '/')
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost" && name[:i] != "<local>") {
domain, remainder = defaultDomain, name
} else {
domain, remainder = name[:i], name[i+1:]
}
if domain == legacyDefaultDomain {
domain = defaultDomain
if domain == "index.docker.io" {
domain = "docker.io"
}
if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {
remainder = officialRepoName + "/" + remainder
Expand All @@ -76,9 +75,9 @@ func splitDockerDomain(name string) (domain, remainder string) {

// familiarizeName returns a shortened version of the name familiar
// to to the Docker UI. Familiar names have the default domain
// "docker.io" and "library/" repository prefix removed.
// For example, "docker.io/library/redis" will have the familiar
// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp".
// "<local>" and "library/" repository prefix removed.
// For example, "<local>/library/redis" will have the familiar
// name "redis" and "<local>/dmcgowan/myapp" will be "dmcgowan/myapp".
// Returns a familiarized named only reference.
func familiarizeName(named namedRepository) repository {
repo := repository{
Expand Down
56 changes: 28 additions & 28 deletions docker/reference/normalize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,31 +132,31 @@ func TestParseRepositoryInfo(t *testing.T) {
tcases := []tcase{
{
RemoteName: "fooo/bar",
FamiliarName: "fooo/bar",
FamiliarName: "docker.io/fooo/bar",
FullName: "docker.io/fooo/bar",
AmbiguousName: "index.docker.io/fooo/bar",
Domain: "docker.io",
},
{
RemoteName: "library/ubuntu",
FamiliarName: "ubuntu",
FullName: "docker.io/library/ubuntu",
FullName: "<local>/library/ubuntu",
AmbiguousName: "library/ubuntu",
Domain: "docker.io",
Domain: "<local>",
},
{
RemoteName: "nonlibrary/ubuntu",
FamiliarName: "nonlibrary/ubuntu",
FullName: "docker.io/nonlibrary/ubuntu",
FullName: "<local>/nonlibrary/ubuntu",
AmbiguousName: "",
Domain: "docker.io",
Domain: "<local>",
},
{
RemoteName: "other/library",
FamiliarName: "other/library",
FullName: "docker.io/other/library",
FullName: "<local>/other/library",
AmbiguousName: "",
Domain: "docker.io",
Domain: "<local>",
},
{
RemoteName: "private/moonbase",
Expand Down Expand Up @@ -202,31 +202,31 @@ func TestParseRepositoryInfo(t *testing.T) {
},
{
RemoteName: "library/ubuntu-12.04-base",
FamiliarName: "ubuntu-12.04-base",
FamiliarName: "docker.io/library/ubuntu-12.04-base",
FullName: "docker.io/library/ubuntu-12.04-base",
AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
Domain: "docker.io",
},
{
RemoteName: "library/foo",
FamiliarName: "foo",
FullName: "docker.io/library/foo",
AmbiguousName: "docker.io/foo",
Domain: "docker.io",
FullName: "<local>/library/foo",
AmbiguousName: "<local>/foo",
Domain: "<local>",
},
{
RemoteName: "library/foo/bar",
FamiliarName: "library/foo/bar",
FullName: "docker.io/library/foo/bar",
FullName: "<local>/library/foo/bar",
AmbiguousName: "",
Domain: "docker.io",
Domain: "<local>",
},
{
RemoteName: "store/foo/bar",
FamiliarName: "store/foo/bar",
FullName: "docker.io/store/foo/bar",
FullName: "<local>/store/foo/bar",
AmbiguousName: "",
Domain: "docker.io",
Domain: "<local>",
},
}

Expand Down Expand Up @@ -269,7 +269,7 @@ func TestParseReferenceWithTagAndDigest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if expected, actual := "docker.io/library/"+shortRef, ref.String(); actual != expected {
if expected, actual := "<local>/library/"+shortRef, ref.String(); actual != expected {
t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual)
}

Expand Down Expand Up @@ -334,39 +334,39 @@ func TestParseAnyReference(t *testing.T) {
}{
{
Reference: "redis",
Equivalent: "docker.io/library/redis",
Equivalent: "<local>/library/redis",
},
{
Reference: "redis:latest",
Equivalent: "docker.io/library/redis:latest",
Equivalent: "<local>/library/redis:latest",
},
{
Reference: "docker.io/library/redis:latest",
Equivalent: "docker.io/library/redis:latest",
},
{
Reference: "redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Equivalent: "<local>/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
},
{
Reference: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
},
{
Reference: "dmcgowan/myapp",
Equivalent: "docker.io/dmcgowan/myapp",
Equivalent: "<local>/dmcgowan/myapp",
},
{
Reference: "dmcgowan/myapp:latest",
Equivalent: "docker.io/dmcgowan/myapp:latest",
Equivalent: "<local>/dmcgowan/myapp:latest",
},
{
Reference: "docker.io/mcgowan/myapp:latest",
Equivalent: "docker.io/mcgowan/myapp:latest",
},
{
Reference: "dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Equivalent: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Equivalent: "<local>/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
},
{
Reference: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
Expand All @@ -384,7 +384,7 @@ func TestParseAnyReference(t *testing.T) {
},
{
Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
Equivalent: "docker.io/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
Equivalent: "<local>/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
},
}

Expand Down Expand Up @@ -425,12 +425,12 @@ func TestNormalizedSplitHostname(t *testing.T) {
},
{
input: "test_com/foo",
domain: "docker.io",
domain: "<local>",
name: "test_com/foo",
},
{
input: "docker/migrator",
domain: "docker.io",
domain: "<local>",
name: "docker/migrator",
},
{
Expand All @@ -445,7 +445,7 @@ func TestNormalizedSplitHostname(t *testing.T) {
},
{
input: "foo",
domain: "docker.io",
domain: "<local>",
name: "library/foo",
},
{
Expand All @@ -459,8 +459,8 @@ func TestNormalizedSplitHostname(t *testing.T) {
name: "foo",
},
{
input: "docker.io/foo",
domain: "docker.io",
input: "<local>/foo",
domain: "<local>",
name: "library/foo",
},
{
Expand Down
2 changes: 1 addition & 1 deletion docker/reference/reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ func TestParseNamed(t *testing.T) {
},
// Ambiguous case, parser will add "library/" to foo
{
input: "docker.io/foo",
input: "<local>/foo",
err: ErrNameNotCanonical,
},
}
Expand Down
2 changes: 2 additions & 0 deletions docker/reference/regexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ var (
// allowed by DNS to ensure backwards compatibility with Docker image
// names.
domainRegexp = expression(
optional(literal(`<`)),
domainComponentRegexp,
optional(literal(`>`)),
optional(repeated(literal(`.`), domainComponentRegexp)),
optional(literal(`:`), match(`[0-9]+`)))

Expand Down
2 changes: 1 addition & 1 deletion signature/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestVerifyDockerManifestSignature(t *testing.T) {
assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest)

// Verification using a different canonicalization of TestImageSignatureReference
sig, err = VerifyDockerManifestSignature(signature, manifest, "docker.io/"+TestImageSignatureReference, mech, TestKeyFingerprint)
sig, err = VerifyDockerManifestSignature(signature, manifest, "<local>/"+TestImageSignatureReference, mech, TestKeyFingerprint)
require.NoError(t, err)
assert.Equal(t, TestImageSignatureReference, sig.DockerReference)
assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest)
Expand Down
Loading