summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/server/router/plugin/backend.go2
-rw-r--r--api/server/router/plugin/plugin_routes.go47
-rw-r--r--api/types/reference/image_reference.go34
-rw-r--r--api/types/reference/image_reference_test.go73
-rw-r--r--builder/builder.go2
-rw-r--r--builder/dockerfile/builder.go13
-rw-r--r--cli/command/container/create.go6
-rw-r--r--cli/command/formatter/disk_usage.go4
-rw-r--r--cli/command/formatter/image.go4
-rw-r--r--cli/command/formatter/service.go13
-rw-r--r--cli/command/image/build.go4
-rw-r--r--cli/command/image/pull.go8
-rw-r--r--cli/command/image/trust.go16
-rw-r--r--cli/command/plugin/install.go20
-rw-r--r--cli/command/plugin/push.go7
-rw-r--r--cli/command/plugin/upgrade.go12
-rw-r--r--cli/command/service/trust.go12
-rw-r--r--cli/command/task/print.go14
-rw-r--r--cli/trust/trust.go4
-rw-r--r--client/container_commit.go14
-rw-r--r--client/image_create.go8
-rw-r--r--client/image_import.go2
-rw-r--r--client/image_pull.go27
-rw-r--r--client/image_pull_test.go2
-rw-r--r--client/image_push.go18
-rw-r--r--client/image_push_test.go2
-rw-r--r--client/image_tag.go17
-rw-r--r--client/plugin_install.go2
-rw-r--r--client/plugin_upgrade.go2
-rw-r--r--daemon/cluster/cluster.go48
-rw-r--r--daemon/cluster/executor/backend.go2
-rw-r--r--daemon/cluster/executor/container/adapter.go4
-rw-r--r--daemon/cluster/executor/container/container.go6
-rw-r--r--daemon/commit.go13
-rw-r--r--daemon/daemon.go6
-rw-r--r--daemon/daemon_solaris.go4
-rw-r--r--daemon/errors.go18
-rw-r--r--daemon/events/filter.go6
-rw-r--r--daemon/image.go36
-rw-r--r--daemon/image_delete.go15
-rw-r--r--daemon/image_history.go4
-rw-r--r--daemon/image_inspect.go6
-rw-r--r--daemon/image_pull.go12
-rw-r--r--daemon/image_push.go4
-rw-r--r--daemon/image_tag.go8
-rw-r--r--daemon/images.go6
-rw-r--r--daemon/import.go7
-rw-r--r--daemon/prune.go2
-rw-r--r--distribution/config.go4
-rw-r--r--distribution/errors.go8
-rw-r--r--distribution/pull.go27
-rw-r--r--distribution/pull_v1.go34
-rw-r--r--distribution/pull_v2.go21
-rw-r--r--distribution/pull_v2_test.go4
-rw-r--r--distribution/push.go16
-rw-r--r--distribution/push_v1.go10
-rw-r--r--distribution/push_v2.go61
-rw-r--r--distribution/push_v2_test.go52
-rw-r--r--distribution/registry.go8
-rw-r--r--distribution/registry_unit_test.go6
-rw-r--r--image/tarexport/load.go10
-rw-r--r--image/tarexport/save.go52
-rw-r--r--image/tarexport/tarexport.go6
-rw-r--r--integration-cli/docker_cli_images_test.go2
-rw-r--r--migrate/v1/migratev1.go15
-rw-r--r--migrate/v1/migratev1_test.go8
-rw-r--r--plugin/backend_linux.go26
-rw-r--r--plugin/backend_unsupported.go2
-rw-r--r--plugin/store.go10
-rw-r--r--reference/reference.go194
-rw-r--r--reference/reference_test.go275
-rw-r--r--reference/store.go117
-rw-r--r--reference/store_test.go31
-rw-r--r--registry/config.go13
-rw-r--r--registry/registry_mock_test.go2
-rw-r--r--registry/registry_test.go21
-rw-r--r--registry/session.go20
-rw-r--r--registry/types.go4
78 files changed, 538 insertions, 1117 deletions
diff --git a/api/server/router/plugin/backend.go b/api/server/router/plugin/backend.go
index f4ce9a5af5..a5f3c9790a 100644
--- a/api/server/router/plugin/backend.go
+++ b/api/server/router/plugin/backend.go
@@ -4,9 +4,9 @@ import (
"io"
"net/http"
+ "github.com/docker/distribution/reference"
enginetypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/reference"
"golang.org/x/net/context"
)
diff --git a/api/server/router/plugin/plugin_routes.go b/api/server/router/plugin/plugin_routes.go
index 07cd1f64ef..0d743a4a95 100644
--- a/api/server/router/plugin/plugin_routes.go
+++ b/api/server/router/plugin/plugin_routes.go
@@ -7,13 +7,12 @@ import (
"strconv"
"strings"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/streamformatter"
- "github.com/docker/docker/reference"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@@ -47,39 +46,27 @@ func parseHeaders(headers http.Header) (map[string][]string, *types.AuthConfig)
// be returned.
func parseRemoteRef(remote string) (reference.Named, string, error) {
// Parse remote reference, supporting remotes with name and tag
- // NOTE: Using distribution reference to handle references
- // containing both a name and digest
- remoteRef, err := distreference.ParseNamed(remote)
+ remoteRef, err := reference.ParseNormalizedNamed(remote)
if err != nil {
return nil, "", err
}
- var tag string
- if t, ok := remoteRef.(distreference.Tagged); ok {
- tag = t.Tag()
+ type canonicalWithTag interface {
+ reference.Canonical
+ Tag() string
}
- // Convert distribution reference to docker reference
- // TODO: remove when docker reference changes reconciled upstream
- ref, err := reference.WithName(remoteRef.Name())
- if err != nil {
- return nil, "", err
- }
- if d, ok := remoteRef.(distreference.Digested); ok {
- ref, err = reference.WithDigest(ref, d.Digest())
- if err != nil {
- return nil, "", err
- }
- } else if tag != "" {
- ref, err = reference.WithTag(ref, tag)
+ if canonical, ok := remoteRef.(canonicalWithTag); ok {
+ remoteRef, err = reference.WithDigest(reference.TrimNamed(remoteRef), canonical.Digest())
if err != nil {
return nil, "", err
}
- } else {
- ref = reference.WithDefaultTag(ref)
+ return remoteRef, canonical.Tag(), nil
}
- return ref, tag, nil
+ remoteRef = reference.TagNameOnly(remoteRef)
+
+ return remoteRef, "", nil
}
func (pr *pluginRouter) getPrivileges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -188,24 +175,24 @@ func getName(ref reference.Named, tag, name string) (string, error) {
if err != nil {
return "", err
}
- name = nt.String()
+ name = reference.FamiliarString(nt)
} else {
- name = reference.WithDefaultTag(trimmed).String()
+ name = reference.FamiliarString(reference.TagNameOnly(trimmed))
}
} else {
- name = ref.String()
+ name = reference.FamiliarString(ref)
}
} else {
- localRef, err := reference.ParseNamed(name)
+ localRef, err := reference.ParseNormalizedNamed(name)
if err != nil {
return "", err
}
if _, ok := localRef.(reference.Canonical); ok {
return "", errors.New("cannot use digest in plugin tag")
}
- if distreference.IsNameOnly(localRef) {
+ if reference.IsNameOnly(localRef) {
// TODO: log change in name to out stream
- name = reference.WithDefaultTag(localRef).String()
+ name = reference.FamiliarString(reference.TagNameOnly(localRef))
}
}
return name, nil
diff --git a/api/types/reference/image_reference.go b/api/types/reference/image_reference.go
deleted file mode 100644
index be9cf8ebed..0000000000
--- a/api/types/reference/image_reference.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package reference
-
-import (
- distreference "github.com/docker/distribution/reference"
-)
-
-// Parse parses the given references and returns the repository and
-// tag (if present) from it. If there is an error during parsing, it will
-// return an error.
-func Parse(ref string) (string, string, error) {
- distributionRef, err := distreference.ParseNamed(ref)
- if err != nil {
- return "", "", err
- }
-
- tag := GetTagFromNamedRef(distributionRef)
- return distributionRef.Name(), tag, nil
-}
-
-// GetTagFromNamedRef returns a tag from the specified reference.
-// This function is necessary as long as the docker "server" api makes the distinction between repository
-// and tags.
-func GetTagFromNamedRef(ref distreference.Named) string {
- var tag string
- switch x := ref.(type) {
- case distreference.Digested:
- tag = x.Digest().String()
- case distreference.NamedTagged:
- tag = x.Tag()
- default:
- tag = "latest"
- }
- return tag
-}
diff --git a/api/types/reference/image_reference_test.go b/api/types/reference/image_reference_test.go
deleted file mode 100644
index 2f6268f5bc..0000000000
--- a/api/types/reference/image_reference_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package reference
-
-import (
- _ "crypto/sha256"
- "testing"
-)
-
-func TestParse(t *testing.T) {
- testCases := []struct {
- ref string
- expectedName string
- expectedTag string
- expectedError bool
- }{
- {
- ref: "",
- expectedName: "",
- expectedTag: "",
- expectedError: true,
- },
- {
- ref: "repository",
- expectedName: "repository",
- expectedTag: "latest",
- expectedError: false,
- },
- {
- ref: "repository:tag",
- expectedName: "repository",
- expectedTag: "tag",
- expectedError: false,
- },
- {
- ref: "test.com/repository",
- expectedName: "test.com/repository",
- expectedTag: "latest",
- expectedError: false,
- },
- {
- ref: "test.com:5000/test/repository",
- expectedName: "test.com:5000/test/repository",
- expectedTag: "latest",
- expectedError: false,
- },
- {
- ref: "test.com:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- expectedName: "test.com:5000/repo",
- expectedTag: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- expectedError: false,
- },
- {
- ref: "test.com:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- expectedName: "test.com:5000/repo",
- expectedTag: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- expectedError: false,
- },
- }
-
- for _, c := range testCases {
- name, tag, err := Parse(c.ref)
- if err != nil && c.expectedError {
- continue
- } else if err != nil {
- t.Fatalf("error with %s: %s", c.ref, err.Error())
- }
- if name != c.expectedName {
- t.Fatalf("expected name %s, got %s", c.expectedName, name)
- }
- if tag != c.expectedTag {
- t.Fatalf("expected tag %s, got %s", c.expectedTag, tag)
- }
- }
-}
diff --git a/builder/builder.go b/builder/builder.go
index 42b601e8d8..a98ca29f67 100644
--- a/builder/builder.go
+++ b/builder/builder.go
@@ -9,11 +9,11 @@ import (
"os"
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/image"
- "github.com/docker/docker/reference"
"golang.org/x/net/context"
)
diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go
index 9464c52ca4..9b98c678cd 100644
--- a/builder/dockerfile/builder.go
+++ b/builder/dockerfile/builder.go
@@ -11,6 +11,7 @@ import (
"strings"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
apierrors "github.com/docker/docker/api/errors"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
@@ -19,7 +20,6 @@ import (
"github.com/docker/docker/builder/dockerfile/parser"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
perrors "github.com/pkg/errors"
"golang.org/x/net/context"
)
@@ -176,23 +176,16 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
continue
}
- ref, err := reference.ParseNamed(repo)
+ ref, err := reference.ParseNormalizedNamed(repo)
if err != nil {
return nil, err
}
- ref = reference.WithDefaultTag(ref)
-
if _, isCanonical := ref.(reference.Canonical); isCanonical {
return nil, errors.New("build tag cannot contain a digest")
}
- if _, isTagged := ref.(reference.NamedTagged); !isTagged {
- ref, err = reference.WithTag(ref, reference.DefaultTag)
- if err != nil {
- return nil, err
- }
- }
+ ref = reference.TagNameOnly(ref)
nameWithTag := ref.String()
diff --git a/cli/command/container/create.go b/cli/command/container/create.go
index cfd672e77a..9559ba0c05 100644
--- a/cli/command/container/create.go
+++ b/cli/command/container/create.go
@@ -168,11 +168,7 @@ func createContainer(ctx context.Context, dockerCli *command.DockerCli, config *
return nil, err
}
if named, ok := ref.(reference.Named); ok {
- if reference.IsNameOnly(named) {
- namedRef = reference.EnsureTagged(named)
- } else {
- namedRef = named
- }
+ namedRef = reference.TagNameOnly(named)
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && command.IsTrusted() {
var err error
diff --git a/cli/command/formatter/disk_usage.go b/cli/command/formatter/disk_usage.go
index dc5eec41d7..fd7aabc7c2 100644
--- a/cli/command/formatter/disk_usage.go
+++ b/cli/command/formatter/disk_usage.go
@@ -94,12 +94,12 @@ func (ctx *DiskUsageContext) Write() {
tag := "<none>"
if len(i.RepoTags) > 0 && !isDangling(*i) {
// Only show the first tag
- ref, err := reference.ParseNamed(i.RepoTags[0])
+ ref, err := reference.ParseNormalizedNamed(i.RepoTags[0])
if err != nil {
continue
}
if nt, ok := ref.(reference.NamedTagged); ok {
- repo = ref.Name()
+ repo = reference.FamiliarName(ref)
tag = nt.Tag()
}
}
diff --git a/cli/command/formatter/image.go b/cli/command/formatter/image.go
index 06319b9355..b6508224a3 100644
--- a/cli/command/formatter/image.go
+++ b/cli/command/formatter/image.go
@@ -94,7 +94,7 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
repoTags := map[string][]string{}
repoDigests := map[string][]string{}
- for _, refString := range append(image.RepoTags) {
+ for _, refString := range image.RepoTags {
ref, err := reference.ParseNormalizedNamed(refString)
if err != nil {
continue
@@ -104,7 +104,7 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
}
}
- for _, refString := range append(image.RepoDigests) {
+ for _, refString := range image.RepoDigests {
ref, err := reference.ParseNormalizedNamed(refString)
if err != nil {
continue
diff --git a/cli/command/formatter/service.go b/cli/command/formatter/service.go
index 9d9241b224..8e38cb3a11 100644
--- a/cli/command/formatter/service.go
+++ b/cli/command/formatter/service.go
@@ -5,7 +5,7 @@ import (
"strings"
"time"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command/inspect"
@@ -409,11 +409,12 @@ func (c *serviceContext) Replicas() string {
func (c *serviceContext) Image() string {
c.AddHeader(imageHeader)
image := c.service.Spec.TaskTemplate.ContainerSpec.Image
- if ref, err := distreference.ParseNamed(image); err == nil {
- // update image string for display
- namedTagged, ok := ref.(distreference.NamedTagged)
- if ok {
- image = namedTagged.Name() + ":" + namedTagged.Tag()
+ if ref, err := reference.ParseNormalizedNamed(image); err == nil {
+ // update image string for display, (strips any digest)
+ if nt, ok := ref.(reference.NamedTagged); ok {
+ if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
+ image = reference.FamiliarString(namedTagged)
+ }
}
}
diff --git a/cli/command/image/build.go b/cli/command/image/build.go
index 34e0a39500..96d90cf585 100644
--- a/cli/command/image/build.go
+++ b/cli/command/image/build.go
@@ -397,9 +397,7 @@ func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator
if err != nil {
return nil, nil, err
}
- if reference.IsNameOnly(ref) {
- ref = reference.EnsureTagged(ref)
- }
+ ref = reference.TagNameOnly(ref)
if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() {
trustedRef, err := translator(ctx, ref)
if err != nil {
diff --git a/cli/command/image/pull.go b/cli/command/image/pull.go
index 967beca86f..515273d43c 100644
--- a/cli/command/image/pull.go
+++ b/cli/command/image/pull.go
@@ -42,7 +42,6 @@ func NewPullCommand(dockerCli *command.DockerCli) *cobra.Command {
}
func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
- var distributionRef reference.Named
distributionRef, err := reference.ParseNormalizedNamed(opts.remote)
if err != nil {
return err
@@ -52,9 +51,10 @@ func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
}
if !opts.all && reference.IsNameOnly(distributionRef) {
- taggedRef := reference.EnsureTagged(distributionRef)
- fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", taggedRef.Tag())
- distributionRef = taggedRef
+ distributionRef = reference.TagNameOnly(distributionRef)
+ if tagged, ok := distributionRef.(reference.Tagged); ok {
+ fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag())
+ }
}
// Resolve the Repository name from fqn to RepositoryInfo
diff --git a/cli/command/image/trust.go b/cli/command/image/trust.go
index 2ff9b463d5..8332dd7deb 100644
--- a/cli/command/image/trust.go
+++ b/cli/command/image/trust.go
@@ -129,15 +129,15 @@ func PushTrustedReference(cli *command.DockerCli, repoInfo *registry.RepositoryI
// Initialize the notary repository with a remotely managed snapshot key
if err := repo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil {
- return trust.NotaryError(repoInfo.FullName(), err)
+ return trust.NotaryError(repoInfo.Name.Name(), err)
}
- fmt.Fprintf(cli.Out(), "Finished initializing %q\n", repoInfo.FullName())
+ fmt.Fprintf(cli.Out(), "Finished initializing %q\n", repoInfo.Name.Name())
err = repo.AddTarget(target, data.CanonicalTargetsRole)
case nil:
// already initialized and we have successfully downloaded the latest metadata
err = addTargetToAllSignableRoles(repo, target)
default:
- return trust.NotaryError(repoInfo.FullName(), err)
+ return trust.NotaryError(repoInfo.Name.Name(), err)
}
if err == nil {
@@ -145,11 +145,11 @@ func PushTrustedReference(cli *command.DockerCli, repoInfo *registry.RepositoryI
}
if err != nil {
- fmt.Fprintf(cli.Out(), "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error())
- return trust.NotaryError(repoInfo.FullName(), err)
+ fmt.Fprintf(cli.Out(), "Failed to sign %q:%s - %s\n", repoInfo.Name.Name(), tag, err.Error())
+ return trust.NotaryError(repoInfo.Name.Name(), err)
}
- fmt.Fprintf(cli.Out(), "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
+ fmt.Fprintf(cli.Out(), "Successfully signed %q:%s\n", repoInfo.Name.Name(), tag)
return nil
}
@@ -342,12 +342,12 @@ func TrustedReference(ctx context.Context, cli *command.DockerCli, ref reference
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
- return nil, trust.NotaryError(repoInfo.FullName(), err)
+ return nil, trust.NotaryError(repoInfo.Name.Name(), err)
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
- return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag()))
+ return nil, trust.NotaryError(repoInfo.Name.Name(), fmt.Errorf("No trust data for %s", ref.Tag()))
}
r, err := convertTarget(t.Target)
if err != nil {
diff --git a/cli/command/plugin/install.go b/cli/command/plugin/install.go
index 15877761af..9e9ea40e2a 100644
--- a/cli/command/plugin/install.go
+++ b/cli/command/plugin/install.go
@@ -7,7 +7,6 @@ import (
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
- registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/image"
@@ -54,20 +53,6 @@ func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}
-func getRepoIndexFromUnnormalizedRef(ref reference.Named) (*registrytypes.IndexInfo, error) {
- named, err := reference.ParseNormalizedNamed(ref.Name())
- if err != nil {
- return nil, err
- }
-
- repoInfo, err := registry.ParseRepositoryInfo(named)
- if err != nil {
- return nil, err
- }
-
- return repoInfo.Index, nil
-}
-
type pluginRegistryService struct {
registry.Service
}
@@ -104,9 +89,10 @@ func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts plu
_, isCanonical := ref.(reference.Canonical)
if command.IsTrusted() && !isCanonical {
+ ref = reference.TagNameOnly(ref)
nt, ok := ref.(reference.NamedTagged)
if !ok {
- nt = reference.EnsureTagged(ref)
+ return types.PluginInstallOptions{}, fmt.Errorf("invalid name: %s", ref.String())
}
ctx := context.Background()
@@ -148,7 +134,7 @@ func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
if _, ok := aref.(reference.Canonical); ok {
return fmt.Errorf("invalid name: %s", opts.localName)
}
- localName = reference.FamiliarString(reference.EnsureTagged(aref))
+ localName = reference.FamiliarString(reference.TagNameOnly(aref))
}
ctx := context.Background()
diff --git a/cli/command/plugin/push.go b/cli/command/plugin/push.go
index 6b826dce68..f3643b7f1b 100644
--- a/cli/command/plugin/push.go
+++ b/cli/command/plugin/push.go
@@ -40,10 +40,7 @@ func runPush(dockerCli *command.DockerCli, name string) error {
return fmt.Errorf("invalid name: %s", name)
}
- taggedRef, ok := named.(reference.NamedTagged)
- if !ok {
- taggedRef = reference.EnsureTagged(named)
- }
+ named = reference.TagNameOnly(named)
ctx := context.Background()
@@ -58,7 +55,7 @@ func runPush(dockerCli *command.DockerCli, name string) error {
return err
}
- responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(taggedRef), encodedAuth)
+ responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(named), encodedAuth)
if err != nil {
return err
}
diff --git a/cli/command/plugin/upgrade.go b/cli/command/plugin/upgrade.go
index 6861aa1b32..07f0c7bb91 100644
--- a/cli/command/plugin/upgrade.go
+++ b/cli/command/plugin/upgrade.go
@@ -5,10 +5,10 @@ import (
"fmt"
"strings"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/pkg/jsonmessage"
- "github.com/docker/docker/reference"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -49,19 +49,19 @@ func runUpgrade(dockerCli *command.DockerCli, opts pluginOptions) error {
if opts.remote == "" {
opts.remote = p.PluginReference
}
- remote, err := reference.ParseNamed(opts.remote)
+ remote, err := reference.ParseNormalizedNamed(opts.remote)
if err != nil {
return errors.Wrap(err, "error parsing remote upgrade image reference")
}
- remote = reference.WithDefaultTag(remote)
+ remote = reference.TagNameOnly(remote)
- old, err := reference.ParseNamed(p.PluginReference)
+ old, err := reference.ParseNormalizedNamed(p.PluginReference)
if err != nil {
return errors.Wrap(err, "error parsing current image reference")
}
- old = reference.WithDefaultTag(old)
+ old = reference.TagNameOnly(old)
- fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, old, remote)
+ fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, reference.FamiliarString(old), reference.FamiliarString(remote))
if !opts.skipRemoteCheck && remote.String() != old.String() {
if !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Plugin images do not match, are you sure?") {
return errors.New("canceling upgrade request")
diff --git a/cli/command/service/trust.go b/cli/command/service/trust.go
index d466f3b648..3fd80ae879 100644
--- a/cli/command/service/trust.go
+++ b/cli/command/service/trust.go
@@ -33,10 +33,12 @@ func resolveServiceImageDigest(dockerCli *command.DockerCli, service *swarm.Serv
namedRef, ok := ref.(reference.Named)
if !ok {
return errors.New("failed to resolve image digest using content trust: reference is not named")
-
}
-
- taggedRef := reference.EnsureTagged(namedRef)
+ namedRef = reference.TagNameOnly(namedRef)
+ taggedRef, ok := namedRef.(reference.NamedTagged)
+ if !ok {
+ return errors.New("failed to resolve image digest using content trust: reference is not tagged")
+ }
resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
if err != nil {
@@ -65,12 +67,12 @@ func trustedResolveDigest(ctx context.Context, cli *command.DockerCli, ref refer
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
- return nil, trust.NotaryError(repoInfo.FullName(), err)
+ return nil, trust.NotaryError(repoInfo.Name.Name(), err)
}
// Only get the tag if it's in the top level targets role or the releases delegation role
// ignore it if it's in any other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
- return nil, trust.NotaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", reference.FamiliarString(ref)))
+ return nil, trust.NotaryError(repoInfo.Name.Name(), fmt.Errorf("No trust data for %s", reference.FamiliarString(ref)))
}
logrus.Debugf("retrieving target for %s role\n", t.Role)
diff --git a/cli/command/task/print.go b/cli/command/task/print.go
index 60a2bca85b..d7e20bb59a 100644
--- a/cli/command/task/print.go
+++ b/cli/command/task/print.go
@@ -10,7 +10,7 @@ import (
"golang.org/x/net/context"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/idresolver"
@@ -129,13 +129,15 @@ func print(out io.Writer, ctx context.Context, tasks []swarm.Task, resolver *idr
image := task.Spec.ContainerSpec.Image
if !noTrunc {
- ref, err := distreference.ParseNamed(image)
+ ref, err := reference.ParseNormalizedNamed(image)
if err == nil {
- // update image string for display
- namedTagged, ok := ref.(distreference.NamedTagged)
- if ok {
- image = namedTagged.Name() + ":" + namedTagged.Tag()
+ // update image string for display, (strips any digest)
+ if nt, ok := ref.(reference.NamedTagged); ok {
+ if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
+ image = reference.FamiliarString(namedTagged)
+ }
}
+
}
}
diff --git a/cli/trust/trust.go b/cli/trust/trust.go
index 44f8197ba2..777a611181 100644
--- a/cli/trust/trust.go
+++ b/cli/trust/trust.go
@@ -148,7 +148,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
}
scope := auth.RepositoryScope{
- Repository: repoInfo.FullName(),
+ Repository: repoInfo.Name.Name(),
Actions: actions,
Class: repoInfo.Class,
}
@@ -166,7 +166,7 @@ func GetNotaryRepository(streams command.Streams, repoInfo *registry.RepositoryI
return client.NewNotaryRepository(
trustDirectory(),
- repoInfo.FullName(),
+ repoInfo.Name.Name(),
server,
tr,
getPassphraseRetriever(streams),
diff --git a/client/container_commit.go b/client/container_commit.go
index c766d62e40..531d796ee7 100644
--- a/client/container_commit.go
+++ b/client/container_commit.go
@@ -5,9 +5,8 @@ import (
"errors"
"net/url"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/reference"
"golang.org/x/net/context"
)
@@ -15,17 +14,20 @@ import (
func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) {
var repository, tag string
if options.Reference != "" {
- distributionRef, err := distreference.ParseNamed(options.Reference)
+ ref, err := reference.ParseNormalizedNamed(options.Reference)
if err != nil {
return types.IDResponse{}, err
}
- if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+ if _, isCanonical := ref.(reference.Canonical); isCanonical {
return types.IDResponse{}, errors.New("refusing to create a tag with a digest reference")
}
+ ref = reference.TagNameOnly(ref)
- tag = reference.GetTagFromNamedRef(distributionRef)
- repository = distributionRef.Name()
+ if tagged, ok := ref.(reference.Tagged); ok {
+ tag = tagged.Tag()
+ }
+ repository = reference.FamiliarName(ref)
}
query := url.Values{}
diff --git a/client/image_create.go b/client/image_create.go
index cf023a7186..4436abb0dd 100644
--- a/client/image_create.go
+++ b/client/image_create.go
@@ -6,21 +6,21 @@ import (
"golang.org/x/net/context"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/reference"
)
// ImageCreate creates a new image based in the parent options.
// It returns the JSON content in the response body.
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
- repository, tag, err := reference.Parse(parentReference)
+ ref, err := reference.ParseNormalizedNamed(parentReference)
if err != nil {
return nil, err
}
query := url.Values{}
- query.Set("fromImage", repository)
- query.Set("tag", tag)
+ query.Set("fromImage", reference.FamiliarName(ref))
+ query.Set("tag", getAPITagFromNamedRef(ref))
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if err != nil {
return nil, err
diff --git a/client/image_import.go b/client/image_import.go
index c6f154b249..d7dedd8232 100644
--- a/client/image_import.go
+++ b/client/image_import.go
@@ -15,7 +15,7 @@ import (
func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
if ref != "" {
//Check if the given image name can be resolved
- if _, err := reference.ParseNamed(ref); err != nil {
+ if _, err := reference.ParseNormalizedNamed(ref); err != nil {
return nil, err
}
}
diff --git a/client/image_pull.go b/client/image_pull.go
index 3bffdb70e8..a72b9bf7fc 100644
--- a/client/image_pull.go
+++ b/client/image_pull.go
@@ -7,8 +7,8 @@ import (
"golang.org/x/net/context"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/reference"
)
// ImagePull requests the docker host to pull an image from a remote registry.
@@ -19,16 +19,16 @@ import (
// FIXME(vdemeester): there is currently used in a few way in docker/docker
// - if not in trusted content, ref is used to pass the whole reference, and tag is empty
// - if in trusted content, ref is used to pass the reference name, and tag for the digest
-func (cli *Client) ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
- repository, tag, err := reference.Parse(ref)
+func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) {
+ ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
return nil, err
}
query := url.Values{}
- query.Set("fromImage", repository)
- if tag != "" && !options.All {
- query.Set("tag", tag)
+ query.Set("fromImage", reference.FamiliarName(ref))
+ if !options.All {
+ query.Set("tag", getAPITagFromNamedRef(ref))
}
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
@@ -44,3 +44,18 @@ func (cli *Client) ImagePull(ctx context.Context, ref string, options types.Imag
}
return resp.body, nil
}
+
+// getAPITagFromNamedRef returns a tag from the specified reference.
+// This function is necessary as long as the docker "server" api expects
+// digests to be sent as tags and makes a distinction between the name
+// and tag/digest part of a reference.
+func getAPITagFromNamedRef(ref reference.Named) string {
+ if digested, ok := ref.(reference.Digested); ok {
+ return digested.Digest().String()
+ }
+ ref = reference.TagNameOnly(ref)
+ if tagged, ok := ref.(reference.Tagged); ok {
+ return tagged.Tag()
+ }
+ return ""
+}
diff --git a/client/image_pull_test.go b/client/image_pull_test.go
index fe6bafed97..ab49d2d349 100644
--- a/client/image_pull_test.go
+++ b/client/image_pull_test.go
@@ -21,7 +21,7 @@ func TestImagePullReferenceParseError(t *testing.T) {
}
// An empty reference is an invalid reference
_, err := client.ImagePull(context.Background(), "", types.ImagePullOptions{})
- if err == nil || err.Error() != "repository name must have at least one component" {
+ if err == nil || !strings.Contains(err.Error(), "invalid reference format") {
t.Fatalf("expected an error, got %v", err)
}
}
diff --git a/client/image_push.go b/client/image_push.go
index 8e73d28f56..410d2fb91d 100644
--- a/client/image_push.go
+++ b/client/image_push.go
@@ -8,7 +8,7 @@ import (
"golang.org/x/net/context"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
)
@@ -16,31 +16,33 @@ import (
// It executes the privileged function if the operation is unauthorized
// and it tries one more time.
// It's up to the caller to handle the io.ReadCloser and close it properly.
-func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
- distributionRef, err := distreference.ParseNamed(ref)
+func (cli *Client) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) {
+ ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return nil, err
}
- if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+ if _, isCanonical := ref.(reference.Canonical); isCanonical {
return nil, errors.New("cannot push a digest reference")
}
- var tag = ""
- if nameTaggedRef, isNamedTagged := distributionRef.(distreference.NamedTagged); isNamedTagged {
+ tag := ""
+ name := reference.FamiliarName(ref)
+
+ if nameTaggedRef, isNamedTagged := ref.(reference.NamedTagged); isNamedTagged {
tag = nameTaggedRef.Tag()
}
query := url.Values{}
query.Set("tag", tag)
- resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth)
+ resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil {
return nil, privilegeErr
}
- resp, err = cli.tryImagePush(ctx, distributionRef.Name(), query, newAuthHeader)
+ resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader)
}
if err != nil {
return nil, err
diff --git a/client/image_push_test.go b/client/image_push_test.go
index b52da8b8dc..f93debf5bb 100644
--- a/client/image_push_test.go
+++ b/client/image_push_test.go
@@ -21,7 +21,7 @@ func TestImagePushReferenceError(t *testing.T) {
}
// An empty reference is an invalid reference
_, err := client.ImagePush(context.Background(), "", types.ImagePushOptions{})
- if err == nil || err.Error() != "repository name must have at least one component" {
+ if err == nil || !strings.Contains(err.Error(), "invalid reference format") {
t.Fatalf("expected an error, got %v", err)
}
// An canonical reference cannot be pushed
diff --git a/client/image_tag.go b/client/image_tag.go
index dbcd078e1c..35abe332bf 100644
--- a/client/image_tag.go
+++ b/client/image_tag.go
@@ -3,32 +3,33 @@ package client
import (
"net/url"
- distreference "github.com/docker/distribution/reference"
- "github.com/docker/docker/api/types/reference"
+ "github.com/docker/distribution/reference"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
// ImageTag tags an image in the docker host
func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
- if _, err := distreference.ParseNamed(source); err != nil {
+ if _, err := reference.ParseNormalizedNamed(source); err != nil {
return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", source)
}
- distributionRef, err := distreference.ParseNamed(target)
+ ref, err := reference.ParseNormalizedNamed(target)
if err != nil {
return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", target)
}
- if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+ if _, isCanonical := ref.(reference.Canonical); isCanonical {
return errors.New("refusing to create a tag with a digest reference")
}
- tag := reference.GetTagFromNamedRef(distributionRef)
+ ref = reference.TagNameOnly(ref)
query := url.Values{}
- query.Set("repo", distributionRef.Name())
- query.Set("tag", tag)
+ query.Set("repo", reference.FamiliarName(ref))
+ if tagged, ok := ref.(reference.Tagged); ok {
+ query.Set("tag", tagged.Tag())
+ }
resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil)
ensureReaderClosed(resp)
diff --git a/client/plugin_install.go b/client/plugin_install.go
index 3217c4cf39..33876cc101 100644
--- a/client/plugin_install.go
+++ b/client/plugin_install.go
@@ -15,7 +15,7 @@ import (
// PluginInstall installs a plugin
func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
query := url.Values{}
- if _, err := reference.ParseNamed(options.RemoteRef); err != nil {
+ if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil {
return nil, errors.Wrap(err, "invalid remote reference")
}
query.Set("remote", options.RemoteRef)
diff --git a/client/plugin_upgrade.go b/client/plugin_upgrade.go
index 95a4356b97..24293c5073 100644
--- a/client/plugin_upgrade.go
+++ b/client/plugin_upgrade.go
@@ -14,7 +14,7 @@ import (
// PluginUpgrade upgrades a plugin
func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
query := url.Values{}
- if _, err := reference.ParseNamed(options.RemoteRef); err != nil {
+ if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil {
return nil, errors.Wrap(err, "invalid remote reference")
}
query.Set("remote", options.RemoteRef)
diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go
index 5f32ef85e2..18888d53b6 100644
--- a/daemon/cluster/cluster.go
+++ b/daemon/cluster/cluster.go
@@ -52,7 +52,7 @@ import (
"time"
"github.com/Sirupsen/logrus"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
apierrors "github.com/docker/docker/api/errors"
apitypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
@@ -66,13 +66,11 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/stdcopy"
- "github.com/docker/docker/reference"
"github.com/docker/docker/runconfig"
swarmapi "github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/manager/encryption"
swarmnode "github.com/docker/swarmkit/node"
gogotypes "github.com/gogo/protobuf/types"
- "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@@ -829,50 +827,46 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv
}
// imageWithDigestString takes an image such as name or name:tag
-// and returns the image pinned to a digest, such as name@sha256:34234...
-// Due to the difference between the docker/docker/reference, and the
-// docker/distribution/reference packages, we're parsing the image twice.
-// As the two packages converge, this function should be simplified.
-// TODO(nishanttotla): After the packages converge, the function must
-// convert distreference.Named -> distreference.Canonical, and the logic simplified.
+// and returns the image pinned to a digest, such as name@sha256:34234
func (c *Cluster) imageWithDigestString(ctx context.Context, image string, authConfig *apitypes.AuthConfig) (string, error) {
- if _, err := digest.Parse(image); err == nil {
- return "", errors.New("image reference is an image ID")
- }
- ref, err := distreference.ParseNamed(image)
+ ref, err := reference.ParseAnyReference(image)
if err != nil {
return "", err
}
- // only query registry if not a canonical reference (i.e. with digest)
- if _, ok := ref.(distreference.Canonical); !ok {
- // create a docker/docker/reference Named object because GetRepository needs it
- dockerRef, err := reference.ParseNamed(image)
- if err != nil {
- return "", err
+ namedRef, ok := ref.(reference.Named)
+ if !ok {
+ if _, ok := ref.(reference.Digested); ok {
+ return "", errors.New("image reference is an image ID")
}
- dockerRef = reference.WithDefaultTag(dockerRef)
- namedTaggedRef, ok := dockerRef.(reference.NamedTagged)
+ return "", errors.Errorf("unknown image reference format: %s", image)
+ }
+ // only query registry if not a canonical reference (i.e. with digest)
+ if _, ok := namedRef.(reference.Canonical); !ok {
+ namedRef = reference.TagNameOnly(namedRef)
+
+ taggedRef, ok := namedRef.(reference.NamedTagged)
if !ok {
- return "", errors.New("unable to cast image to NamedTagged reference object")
+ return "", errors.Errorf("image reference not tagged: %s", image)
}
- repo, _, err := c.config.Backend.GetRepository(ctx, namedTaggedRef, authConfig)
+ repo, _, err := c.config.Backend.GetRepository(ctx, taggedRef, authConfig)
if err != nil {
return "", err
}
- dscrptr, err := repo.Tags(ctx).Get(ctx, namedTaggedRef.Tag())
+ dscrptr, err := repo.Tags(ctx).Get(ctx, taggedRef.Tag())
if err != nil {
return "", err
}
- namedDigestedRef, err := distreference.WithDigest(distreference.EnsureTagged(ref), dscrptr.Digest)
+ namedDigestedRef, err := reference.WithDigest(taggedRef, dscrptr.Digest)
if err != nil {
return "", err
}
- return namedDigestedRef.String(), nil
+ // return familiar form until interface updated to return type
+ return reference.FamiliarString(namedDigestedRef), nil
}
// reference already contains a digest, so just return it
- return ref.String(), nil
+ return reference.FamiliarString(ref), nil
}
// CreateService creates a new service in a managed swarm cluster.
diff --git a/daemon/cluster/executor/backend.go b/daemon/cluster/executor/backend.go
index 0f1da38558..6612929cc1 100644
--- a/daemon/cluster/executor/backend.go
+++ b/daemon/cluster/executor/backend.go
@@ -5,6 +5,7 @@ import (
"time"
"github.com/docker/distribution"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
@@ -14,7 +15,6 @@ import (
swarmtypes "github.com/docker/docker/api/types/swarm"
clustertypes "github.com/docker/docker/daemon/cluster/provider"
"github.com/docker/docker/plugin"
- "github.com/docker/docker/reference"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/cluster"
networktypes "github.com/docker/libnetwork/types"
diff --git a/daemon/cluster/executor/container/adapter.go b/daemon/cluster/executor/container/adapter.go
index 565af80f2a..76cfc19766 100644
--- a/daemon/cluster/executor/container/adapter.go
+++ b/daemon/cluster/executor/container/adapter.go
@@ -11,13 +11,13 @@ import (
"time"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/daemon/cluster/convert"
executorpkg "github.com/docker/docker/daemon/cluster/executor"
- "github.com/docker/docker/reference"
"github.com/docker/libnetwork"
"github.com/docker/swarmkit/agent/exec"
"github.com/docker/swarmkit/api"
@@ -60,7 +60,7 @@ func (c *containerAdapter) pullImage(ctx context.Context) error {
// Skip pulling if the image is referenced by digest and already
// exists locally.
- named, err := reference.ParseNamed(spec.Image)
+ named, err := reference.ParseNormalizedNamed(spec.Image)
if err == nil {
if _, ok := named.(reference.Canonical); ok {
_, err := c.backend.LookupImage(spec.Image)
diff --git a/daemon/cluster/executor/container/container.go b/daemon/cluster/executor/container/container.go
index fdb06c25e1..0b733904d5 100644
--- a/daemon/cluster/executor/container/container.go
+++ b/daemon/cluster/executor/container/container.go
@@ -10,6 +10,7 @@ import (
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
enginecontainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
@@ -18,7 +19,6 @@ import (
"github.com/docker/docker/api/types/network"
volumetypes "github.com/docker/docker/api/types/volume"
clustertypes "github.com/docker/docker/daemon/cluster/provider"
- "github.com/docker/docker/reference"
"github.com/docker/go-connections/nat"
"github.com/docker/swarmkit/agent/exec"
"github.com/docker/swarmkit/api"
@@ -132,11 +132,11 @@ func (c *containerConfig) name() string {
func (c *containerConfig) image() string {
raw := c.spec().Image
- ref, err := reference.ParseNamed(raw)
+ ref, err := reference.ParseNormalizedNamed(raw)
if err != nil {
return raw
}
- return reference.WithDefaultTag(ref).String()
+ return reference.FamiliarString(reference.TagNameOnly(ref))
}
func (c *containerConfig) portBindings() nat.PortMap {
diff --git a/daemon/commit.go b/daemon/commit.go
index 1e7bffb1dc..070bf18dcf 100644
--- a/daemon/commit.go
+++ b/daemon/commit.go
@@ -2,12 +2,12 @@ package daemon
import (
"encoding/json"
- "fmt"
"io"
"runtime"
"strings"
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/backend"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder/dockerfile"
@@ -16,7 +16,7 @@ import (
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/ioutils"
- "github.com/docker/docker/reference"
+ "github.com/pkg/errors"
)
// merge merges two Config, the image container configuration (defaults values),
@@ -128,7 +128,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
// It is not possible to commit a running container on Windows and on Solaris.
if (runtime.GOOS == "windows" || runtime.GOOS == "solaris") && container.IsRunning() {
- return "", fmt.Errorf("%+v does not support commit of a running container", runtime.GOOS)
+ return "", errors.Errorf("%+v does not support commit of a running container", runtime.GOOS)
}
if c.Pause && !container.IsPaused() {
@@ -228,10 +228,13 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
imageRef := ""
if c.Repo != "" {
- newTag, err := reference.WithName(c.Repo) // todo: should move this to API layer
+ newTag, err := reference.ParseNormalizedNamed(c.Repo) // todo: should move this to API layer
if err != nil {
return "", err
}
+ if !reference.IsNameOnly(newTag) {
+ return "", errors.Errorf("unexpected repository name: %s", c.Repo)
+ }
if c.Tag != "" {
if newTag, err = reference.WithTag(newTag, c.Tag); err != nil {
return "", err
@@ -240,7 +243,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
if err := daemon.TagImageWithReference(id, newTag); err != nil {
return "", err
}
- imageRef = newTag.String()
+ imageRef = reference.FamiliarString(newTag)
}
attributes := map[string]string{
diff --git a/daemon/daemon.go b/daemon/daemon.go
index 492dd0252d..560b89a419 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -46,7 +46,7 @@ import (
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/truncindex"
"github.com/docker/docker/plugin"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/docker/docker/runconfig"
volumedrivers "github.com/docker/docker/volume/drivers"
@@ -76,7 +76,7 @@ type Daemon struct {
repository string
containers container.Store
execCommands *exec.Store
- referenceStore reference.Store
+ referenceStore refstore.Store
downloadManager *xfer.LayerDownloadManager
uploadManager *xfer.LayerUploadManager
distributionMetadataStore dmetadata.Store
@@ -637,7 +637,7 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
eventsService := events.New()
- referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json"))
+ referenceStore, err := refstore.NewReferenceStore(filepath.Join(imageRoot, "repositories.json"))
if err != nil {
return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err)
}
diff --git a/daemon/daemon_solaris.go b/daemon/daemon_solaris.go
index 17a593f56b..0f514e4305 100644
--- a/daemon/daemon_solaris.go
+++ b/daemon/daemon_solaris.go
@@ -16,7 +16,7 @@ import (
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/sysinfo"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/docker/libnetwork"
nwconfig "github.com/docker/libnetwork/config"
"github.com/docker/libnetwork/drivers/solaris/bridge"
@@ -491,7 +491,7 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container
return daemon.Unmount(container)
}
-func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) error {
+func restoreCustomImage(is image.Store, ls layer.Store, rs refstore.Store) error {
// Solaris has no custom images to register
return nil
}
diff --git a/daemon/errors.go b/daemon/errors.go
index 566a32f175..96c30df2ea 100644
--- a/daemon/errors.go
+++ b/daemon/errors.go
@@ -2,29 +2,13 @@ package daemon
import (
"fmt"
- "strings"
"github.com/docker/docker/api/errors"
- "github.com/docker/docker/reference"
)
func (d *Daemon) imageNotExistToErrcode(err error) error {
if dne, isDNE := err.(ErrImageDoesNotExist); isDNE {
- if strings.Contains(dne.RefOrID, "@") {
- e := fmt.Errorf("No such image: %s", dne.RefOrID)
- return errors.NewRequestNotFoundError(e)
- }
- tag := reference.DefaultTag
- ref, err := reference.ParseNamed(dne.RefOrID)
- if err != nil {
- e := fmt.Errorf("No such image: %s:%s", dne.RefOrID, tag)
- return errors.NewRequestNotFoundError(e)
- }
- if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
- tag = tagged.Tag()
- }
- e := fmt.Errorf("No such image: %s:%s", ref.Name(), tag)
- return errors.NewRequestNotFoundError(e)
+ return errors.NewRequestNotFoundError(dne)
}
return err
}
diff --git a/daemon/events/filter.go b/daemon/events/filter.go
index 5c9c527692..d10051600e 100644
--- a/daemon/events/filter.go
+++ b/daemon/events/filter.go
@@ -1,9 +1,9 @@
package events
import (
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/reference"
)
// Filter can filter out docker events from a stream
@@ -102,9 +102,9 @@ func (ef *Filter) matchImage(ev events.Message) bool {
}
func stripTag(image string) string {
- ref, err := reference.ParseNamed(image)
+ ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return image
}
- return ref.Name()
+ return reference.FamiliarName(ref)
}
diff --git a/daemon/image.go b/daemon/image.go
index 32a8d77432..43ee483ff0 100644
--- a/daemon/image.go
+++ b/daemon/image.go
@@ -3,45 +3,55 @@ package daemon
import (
"fmt"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/builder"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
)
// ErrImageDoesNotExist is error returned when no image can be found for a reference.
type ErrImageDoesNotExist struct {
- RefOrID string
+ ref reference.Reference
}
func (e ErrImageDoesNotExist) Error() string {
- return fmt.Sprintf("no such id: %s", e.RefOrID)
+ ref := e.ref
+ if named, ok := ref.(reference.Named); ok {
+ ref = reference.TagNameOnly(named)
+ }
+ return fmt.Sprintf("No such image: %s", reference.FamiliarString(ref))
}
// GetImageID returns an image ID corresponding to the image referred to by
// refOrID.
func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
- id, ref, err := reference.ParseIDOrReference(refOrID)
+ ref, err := reference.ParseAnyReference(refOrID)
if err != nil {
return "", err
}
- if id != "" {
- if _, err := daemon.imageStore.Get(image.IDFromDigest(id)); err != nil {
- return "", ErrImageDoesNotExist{refOrID}
+ namedRef, ok := ref.(reference.Named)
+ if !ok {
+ digested, ok := ref.(reference.Digested)
+ if !ok {
+ return "", ErrImageDoesNotExist{ref}
}
- return image.IDFromDigest(id), nil
+ id := image.IDFromDigest(digested.Digest())
+ if _, err := daemon.imageStore.Get(id); err != nil {
+ return "", ErrImageDoesNotExist{ref}
+ }
+ return id, nil
}
- if id, err := daemon.referenceStore.Get(ref); err == nil {
+ if id, err := daemon.referenceStore.Get(namedRef); err == nil {
return image.IDFromDigest(id), nil
}
// deprecated: repo:shortid https://github.com/docker/docker/pull/799
- if tagged, ok := ref.(reference.NamedTagged); ok {
+ if tagged, ok := namedRef.(reference.Tagged); ok {
if tag := tagged.Tag(); stringid.IsShortID(stringid.TruncateID(tag)) {
if id, err := daemon.imageStore.Search(tag); err == nil {
- for _, namedRef := range daemon.referenceStore.References(id.Digest()) {
- if namedRef.Name() == ref.Name() {
+ for _, storeRef := range daemon.referenceStore.References(id.Digest()) {
+ if storeRef.Name() == namedRef.Name() {
return id, nil
}
}
@@ -54,7 +64,7 @@ func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
return id, nil
}
- return "", ErrImageDoesNotExist{refOrID}
+ return "", ErrImageDoesNotExist{ref}
}
// GetImage returns an image corresponding to the image referred to by refOrID.
diff --git a/daemon/image_delete.go b/daemon/image_delete.go
index 30854e3f90..b7dbd249eb 100644
--- a/daemon/image_delete.go
+++ b/daemon/image_delete.go
@@ -5,12 +5,12 @@ import (
"strings"
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/errors"
"github.com/docker/docker/api/types"
"github.com/docker/docker/container"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
)
type conflictType int
@@ -89,7 +89,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
}
}
- parsedRef, err := reference.ParseNamed(imageRef)
+ parsedRef, err := reference.ParseNormalizedNamed(imageRef)
if err != nil {
return nil, err
}
@@ -99,7 +99,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
return nil, err
}
- untaggedRecord := types.ImageDeleteResponseItem{Untagged: parsedRef.String()}
+ untaggedRecord := types.ImageDeleteResponseItem{Untagged: reference.FamiliarString(parsedRef)}
daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
records = append(records, untaggedRecord)
@@ -126,7 +126,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
return records, err
}
- untaggedRecord := types.ImageDeleteResponseItem{Untagged: repoRef.String()}
+ untaggedRecord := types.ImageDeleteResponseItem{Untagged: reference.FamiliarString(repoRef)}
records = append(records, untaggedRecord)
} else {
remainingRefs = append(remainingRefs, repoRef)
@@ -162,7 +162,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
return nil, err
}
- untaggedRecord := types.ImageDeleteResponseItem{Untagged: parsedRef.String()}
+ untaggedRecord := types.ImageDeleteResponseItem{Untagged: reference.FamiliarString(parsedRef)}
daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
records = append(records, untaggedRecord)
@@ -232,7 +232,8 @@ func (daemon *Daemon) getContainerUsingImage(imageID image.ID) *container.Contai
// optional tag or digest reference. If tag or digest is omitted, the default
// tag is used. Returns the resolved image reference and an error.
func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, error) {
- ref = reference.WithDefaultTag(ref)
+ ref = reference.TagNameOnly(ref)
+
// Ignore the boolean value returned, as far as we're concerned, this
// is an idempotent operation and it's okay if the reference didn't
// exist in the first place.
@@ -255,7 +256,7 @@ func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]ty
return err
}
- untaggedRecord := types.ImageDeleteResponseItem{Untagged: parsedRef.String()}
+ untaggedRecord := types.ImageDeleteResponseItem{Untagged: reference.FamiliarString(parsedRef)}
daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
*records = append(*records, untaggedRecord)
diff --git a/daemon/image_history.go b/daemon/image_history.go
index 9e544963b1..b763c86c03 100644
--- a/daemon/image_history.go
+++ b/daemon/image_history.go
@@ -4,9 +4,9 @@ import (
"fmt"
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/layer"
- "github.com/docker/docker/reference"
)
// ImageHistory returns a slice of ImageHistory structures for the specified image
@@ -64,7 +64,7 @@ func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, e
var tags []string
for _, r := range daemon.referenceStore.References(id.Digest()) {
if _, ok := r.(reference.NamedTagged); ok {
- tags = append(tags, r.String())
+ tags = append(tags, reference.FamiliarString(r))
}
}
diff --git a/daemon/image_inspect.go b/daemon/image_inspect.go
index 5a05247099..267a41946a 100644
--- a/daemon/image_inspect.go
+++ b/daemon/image_inspect.go
@@ -3,9 +3,9 @@ package daemon
import (
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/layer"
- "github.com/docker/docker/reference"
"github.com/pkg/errors"
)
@@ -23,9 +23,9 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
for _, ref := range refs {
switch ref.(type) {
case reference.NamedTagged:
- repoTags = append(repoTags, ref.String())
+ repoTags = append(repoTags, reference.FamiliarString(ref))
case reference.Canonical:
- repoDigests = append(repoDigests, ref.String())
+ repoDigests = append(repoDigests, reference.FamiliarString(ref))
}
}
diff --git a/daemon/image_pull.go b/daemon/image_pull.go
index f1b5f83c79..5cbd7ba42a 100644
--- a/daemon/image_pull.go
+++ b/daemon/image_pull.go
@@ -5,12 +5,12 @@ import (
"strings"
dist "github.com/docker/distribution"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/builder"
"github.com/docker/docker/distribution"
progressutils "github.com/docker/docker/distribution/utils"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
"golang.org/x/net/context"
@@ -24,7 +24,7 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHead
// compatibility.
image = strings.TrimSuffix(image, ":")
- ref, err := reference.ParseNamed(image)
+ ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return err
}
@@ -48,11 +48,11 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHead
// PullOnBuild tells Docker to pull image referenced by `name`.
func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
- ref, err := reference.ParseNamed(name)
+ ref, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
- ref = reference.WithDefaultTag(ref)
+ ref = reference.TagNameOnly(ref)
pullRegistryAuth := &types.AuthConfig{}
if len(authConfigs) > 0 {
@@ -118,12 +118,12 @@ func (daemon *Daemon) GetRepository(ctx context.Context, ref reference.NamedTagg
return nil, false, err
}
// makes sure name is not empty or `scratch`
- if err := distribution.ValidateRepoName(repoInfo.Name()); err != nil {
+ if err := distribution.ValidateRepoName(repoInfo.Name); err != nil {
return nil, false, err
}
// get endpoints
- endpoints, err := daemon.RegistryService.LookupPullEndpoints(repoInfo.Hostname())
+ endpoints, err := daemon.RegistryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
if err != nil {
return nil, false, err
}
diff --git a/daemon/image_push.go b/daemon/image_push.go
index e6382c7f27..0f060d117f 100644
--- a/daemon/image_push.go
+++ b/daemon/image_push.go
@@ -4,17 +4,17 @@ import (
"io"
"github.com/docker/distribution/manifest/schema2"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/distribution"
progressutils "github.com/docker/docker/distribution/utils"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
"golang.org/x/net/context"
)
// PushImage initiates a push operation on the repository named localName.
func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
- ref, err := reference.ParseNamed(image)
+ ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return err
}
diff --git a/daemon/image_tag.go b/daemon/image_tag.go
index 36fa3b462e..10a584b361 100644
--- a/daemon/image_tag.go
+++ b/daemon/image_tag.go
@@ -1,8 +1,8 @@
package daemon
import (
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/image"
- "github.com/docker/docker/reference"
)
// TagImage creates the tag specified by newTag, pointing to the image named
@@ -13,12 +13,12 @@ func (daemon *Daemon) TagImage(imageName, repository, tag string) error {
return err
}
- newTag, err := reference.WithName(repository)
+ newTag, err := reference.ParseNormalizedNamed(repository)
if err != nil {
return err
}
if tag != "" {
- if newTag, err = reference.WithTag(newTag, tag); err != nil {
+ if newTag, err = reference.WithTag(reference.TrimNamed(newTag), tag); err != nil {
return err
}
}
@@ -32,6 +32,6 @@ func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.N
return err
}
- daemon.LogImageEvent(imageID.String(), newTag.String(), "tag")
+ daemon.LogImageEvent(imageID.String(), reference.FamiliarString(newTag), "tag")
return nil
}
diff --git a/daemon/images.go b/daemon/images.go
index a8571f6dc9..e6e1945092 100644
--- a/daemon/images.go
+++ b/daemon/images.go
@@ -135,7 +135,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs
var found bool
var matchErr error
for _, pattern := range imageFilters.Get("reference") {
- found, matchErr = reference.Match(pattern, ref)
+ found, matchErr = reference.FamiliarMatch(pattern, ref)
if matchErr != nil {
return nil, matchErr
}
@@ -145,10 +145,10 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs
}
}
if _, ok := ref.(reference.Canonical); ok {
- newImage.RepoDigests = append(newImage.RepoDigests, ref.String())
+ newImage.RepoDigests = append(newImage.RepoDigests, reference.FamiliarString(ref))
}
if _, ok := ref.(reference.NamedTagged); ok {
- newImage.RepoTags = append(newImage.RepoTags, ref.String())
+ newImage.RepoTags = append(newImage.RepoTags, reference.FamiliarString(ref))
}
}
if newImage.RepoDigests == nil && newImage.RepoTags == nil {
diff --git a/daemon/import.go b/daemon/import.go
index c93322b92e..adc82550de 100644
--- a/daemon/import.go
+++ b/daemon/import.go
@@ -2,13 +2,13 @@ package daemon
import (
"encoding/json"
- "errors"
"io"
"net/http"
"net/url"
"runtime"
"time"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/dockerversion"
@@ -18,7 +18,7 @@ import (
"github.com/docker/docker/pkg/httputils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
- "github.com/docker/docker/reference"
+ "github.com/pkg/errors"
)
// ImportImage imports an image, getting the archived layer data either from
@@ -35,11 +35,10 @@ func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string
if repository != "" {
var err error
- newRef, err = reference.ParseNamed(repository)
+ newRef, err = reference.ParseNormalizedNamed(repository)
if err != nil {
return err
}
-
if _, isCanonical := newRef.(reference.Canonical); isCanonical {
return errors.New("cannot import digest reference")
}
diff --git a/daemon/prune.go b/daemon/prune.go
index 0c0e554274..2964983137 100644
--- a/daemon/prune.go
+++ b/daemon/prune.go
@@ -6,13 +6,13 @@ import (
"time"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
timetypes "github.com/docker/docker/api/types/time"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/directory"
- "github.com/docker/docker/reference"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/libnetwork"
diff --git a/distribution/config.go b/distribution/config.go
index ab1ab6c003..3490631cf2 100644
--- a/distribution/config.go
+++ b/distribution/config.go
@@ -14,7 +14,7 @@ import (
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/docker/libtrust"
"github.com/opencontainers/go-digest"
@@ -44,7 +44,7 @@ type Config struct {
ImageStore ImageConfigStore
// ReferenceStore manages tags. This value is optional, when excluded
// content will not be tagged.
- ReferenceStore reference.Store
+ ReferenceStore refstore.Store
// RequireSchema2 ensures that only schema2 manifests are used.
RequireSchema2 bool
}
diff --git a/distribution/errors.go b/distribution/errors.go
index b8cf9fb9e8..adf272a5cf 100644
--- a/distribution/errors.go
+++ b/distribution/errors.go
@@ -7,12 +7,12 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/distribution"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/api/v2"
"github.com/docker/distribution/registry/client"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/docker/distribution/xfer"
- "github.com/docker/docker/reference"
"github.com/pkg/errors"
)
@@ -78,11 +78,11 @@ func TranslatePullError(err error, ref reference.Named) error {
switch v.Code {
case errcode.ErrorCodeDenied:
// ErrorCodeDenied is used when access to the repository was denied
- newErr = errors.Errorf("repository %s not found: does not exist or no pull access", ref.Name())
+ newErr = errors.Errorf("repository %s not found: does not exist or no pull access", reference.FamiliarName(ref))
case v2.ErrorCodeManifestUnknown:
- newErr = errors.Errorf("manifest for %s not found", ref.String())
+ newErr = errors.Errorf("manifest for %s not found", reference.FamiliarString(ref))
case v2.ErrorCodeNameUnknown:
- newErr = errors.Errorf("repository %s not found", ref.Name())
+ newErr = errors.Errorf("repository %s not found", reference.FamiliarName(ref))
}
if newErr != nil {
logrus.Infof("Translating %q to %q", err, newErr)
diff --git a/distribution/pull.go b/distribution/pull.go
index ac52ba1fcb..571beaa7ad 100644
--- a/distribution/pull.go
+++ b/distribution/pull.go
@@ -1,14 +1,14 @@
package distribution
import (
- "errors"
"fmt"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
"golang.org/x/net/context"
@@ -56,12 +56,12 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo
return err
}
- // makes sure name is not empty or `scratch`
- if err := ValidateRepoName(repoInfo.Name()); err != nil {
+ // makes sure name is not `scratch`
+ if err := ValidateRepoName(repoInfo.Name); err != nil {
return err
}
- endpoints, err := imagePullConfig.RegistryService.LookupPullEndpoints(repoInfo.Hostname())
+ endpoints, err := imagePullConfig.RegistryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
if err != nil {
return err
}
@@ -105,7 +105,7 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo
}
}
- logrus.Debugf("Trying to pull %s from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version)
+ logrus.Debugf("Trying to pull %s from %s %s", reference.FamiliarName(repoInfo.Name), endpoint.URL, endpoint.Version)
puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
if err != nil {
@@ -147,12 +147,12 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo
return TranslatePullError(err, ref)
}
- imagePullConfig.ImageEventLogger(ref.String(), repoInfo.Name(), "pull")
+ imagePullConfig.ImageEventLogger(reference.FamiliarString(ref), reference.FamiliarName(repoInfo.Name), "pull")
return nil
}
if lastErr == nil {
- lastErr = fmt.Errorf("no endpoints found for %s", ref.String())
+ lastErr = fmt.Errorf("no endpoints found for %s", reference.FamiliarString(ref))
}
return TranslatePullError(lastErr, ref)
@@ -171,17 +171,14 @@ func writeStatus(requestedTag string, out progress.Output, layersDownloaded bool
}
// ValidateRepoName validates the name of a repository.
-func ValidateRepoName(name string) error {
- if name == "" {
- return errors.New("Repository name can't be empty")
- }
- if name == api.NoBaseImageSpecifier {
+func ValidateRepoName(name reference.Named) error {
+ if reference.FamiliarName(name) == api.NoBaseImageSpecifier {
return fmt.Errorf("'%s' is a reserved name", api.NoBaseImageSpecifier)
}
return nil
}
-func addDigestReference(store reference.Store, ref reference.Named, dgst digest.Digest, id digest.Digest) error {
+func addDigestReference(store refstore.Store, ref reference.Named, dgst digest.Digest, id digest.Digest) error {
dgstRef, err := reference.WithDigest(reference.TrimNamed(ref), dgst)
if err != nil {
return err
@@ -193,7 +190,7 @@ func addDigestReference(store reference.Store, ref reference.Named, dgst digest.
logrus.Errorf("Image ID for digest %s changed from %s to %s, cannot update", dgst.String(), oldTagID, id)
}
return nil
- } else if err != reference.ErrDoesNotExist {
+ } else if err != refstore.ErrDoesNotExist {
return err
}
diff --git a/distribution/pull_v1.go b/distribution/pull_v1.go
index f44ed4f371..d873d338cd 100644
--- a/distribution/pull_v1.go
+++ b/distribution/pull_v1.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client/transport"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/distribution/xfer"
@@ -22,7 +23,6 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"golang.org/x/net/context"
)
@@ -67,23 +67,23 @@ func (p *v1Puller) Pull(ctx context.Context, ref reference.Named) error {
// TODO(dmcgowan): Check if should fallback
return err
}
- progress.Message(p.config.ProgressOutput, "", p.repoInfo.FullName()+": this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.")
+ progress.Message(p.config.ProgressOutput, "", p.repoInfo.Name.Name()+": this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.")
return nil
}
func (p *v1Puller) pullRepository(ctx context.Context, ref reference.Named) error {
- progress.Message(p.config.ProgressOutput, "", "Pulling repository "+p.repoInfo.FullName())
+ progress.Message(p.config.ProgressOutput, "", "Pulling repository "+p.repoInfo.Name.Name())
tagged, isTagged := ref.(reference.NamedTagged)
- repoData, err := p.session.GetRepositoryData(p.repoInfo)
+ repoData, err := p.session.GetRepositoryData(p.repoInfo.Name)
if err != nil {
if strings.Contains(err.Error(), "HTTP code: 404") {
if isTagged {
- return fmt.Errorf("Error: image %s:%s not found", p.repoInfo.RemoteName(), tagged.Tag())
+ return fmt.Errorf("Error: image %s:%s not found", reference.Path(p.repoInfo.Name), tagged.Tag())
}
- return fmt.Errorf("Error: image %s not found", p.repoInfo.RemoteName())
+ return fmt.Errorf("Error: image %s not found", reference.Path(p.repoInfo.Name))
}
// Unexpected HTTP error
return err
@@ -92,13 +92,13 @@ func (p *v1Puller) pullRepository(ctx context.Context, ref reference.Named) erro
logrus.Debug("Retrieving the tag list")
var tagsList map[string]string
if !isTagged {
- tagsList, err = p.session.GetRemoteTags(repoData.Endpoints, p.repoInfo)
+ tagsList, err = p.session.GetRemoteTags(repoData.Endpoints, p.repoInfo.Name)
} else {
var tagID string
tagsList = make(map[string]string)
- tagID, err = p.session.GetRemoteTag(repoData.Endpoints, p.repoInfo, tagged.Tag())
+ tagID, err = p.session.GetRemoteTag(repoData.Endpoints, p.repoInfo.Name, tagged.Tag())
if err == registry.ErrRepoNotFound {
- return fmt.Errorf("Tag %s not found in repository %s", tagged.Tag(), p.repoInfo.FullName())
+ return fmt.Errorf("Tag %s not found in repository %s", tagged.Tag(), p.repoInfo.Name.Name())
}
tagsList[tagged.Tag()] = tagID
}
@@ -127,7 +127,7 @@ func (p *v1Puller) pullRepository(ctx context.Context, ref reference.Named) erro
}
}
- writeStatus(ref.String(), p.config.ProgressOutput, layersDownloaded)
+ writeStatus(reference.FamiliarString(ref), p.config.ProgressOutput, layersDownloaded)
return nil
}
@@ -137,7 +137,7 @@ func (p *v1Puller) downloadImage(ctx context.Context, repoData *registry.Reposit
return nil
}
- localNameRef, err := reference.WithTag(p.repoInfo, img.Tag)
+ localNameRef, err := reference.WithTag(p.repoInfo.Name, img.Tag)
if err != nil {
retErr := fmt.Errorf("Image (id: %s) has invalid tag: %s", img.ID, img.Tag)
logrus.Debug(retErr.Error())
@@ -148,15 +148,15 @@ func (p *v1Puller) downloadImage(ctx context.Context, repoData *registry.Reposit
return err
}
- progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Pulling image (%s) from %s", img.Tag, p.repoInfo.FullName())
+ progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Pulling image (%s) from %s", img.Tag, p.repoInfo.Name.Name())
success := false
var lastErr error
for _, ep := range p.repoInfo.Index.Mirrors {
ep += "v1/"
- progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, p.repoInfo.FullName(), ep))
+ progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, p.repoInfo.Name.Name(), ep))
if err = p.pullImage(ctx, img.ID, ep, localNameRef, layersDownloaded); err != nil {
// Don't report errors when pulling from mirrors.
- logrus.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, p.repoInfo.FullName(), ep, err)
+ logrus.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, p.repoInfo.Name.Name(), ep, err)
continue
}
success = true
@@ -164,12 +164,12 @@ func (p *v1Puller) downloadImage(ctx context.Context, repoData *registry.Reposit
}
if !success {
for _, ep := range repoData.Endpoints {
- progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Pulling image (%s) from %s, endpoint: %s", img.Tag, p.repoInfo.FullName(), ep)
+ progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Pulling image (%s) from %s, endpoint: %s", img.Tag, p.repoInfo.Name.Name(), ep)
if err = p.pullImage(ctx, img.ID, ep, localNameRef, layersDownloaded); err != nil {
// It's not ideal that only the last error is returned, it would be better to concatenate the errors.
// As the error is also given to the output stream the user will see the error.
lastErr = err
- progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, p.repoInfo.FullName(), ep, err)
+ progress.Updatef(p.config.ProgressOutput, stringid.TruncateID(img.ID), "Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, p.repoInfo.Name.Name(), ep, err)
continue
}
success = true
@@ -177,7 +177,7 @@ func (p *v1Puller) downloadImage(ctx context.Context, repoData *registry.Reposit
}
}
if !success {
- err := fmt.Errorf("Error pulling image (%s) from %s, %v", img.Tag, p.repoInfo.FullName(), lastErr)
+ err := fmt.Errorf("Error pulling image (%s) from %s, %v", img.Tag, p.repoInfo.Name.Name(), lastErr)
progress.Update(p.config.ProgressOutput, stringid.TruncateID(img.ID), err.Error())
return err
}
diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go
index e707e7d3b6..14c88fd33b 100644
--- a/distribution/pull_v2.go
+++ b/distribution/pull_v2.go
@@ -15,6 +15,7 @@ import (
"github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/schema1"
"github.com/docker/distribution/manifest/schema2"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/distribution/registry/client/transport"
@@ -26,7 +27,7 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
"golang.org/x/net/context"
@@ -124,7 +125,7 @@ func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named) (e
}
}
- writeStatus(ref.String(), p.config.ProgressOutput, layersDownloaded)
+ writeStatus(reference.FamiliarString(ref), p.config.ProgressOutput, layersDownloaded)
return nil
}
@@ -317,7 +318,7 @@ func (ld *v2LayerDescriptor) truncateDownloadFile() error {
func (ld *v2LayerDescriptor) Registered(diffID layer.DiffID) {
// Cache mapping from this layer's DiffID to the blobsum
- ld.V2MetadataService.Add(diffID, metadata.V2Metadata{Digest: ld.digest, SourceRepository: ld.repoInfo.FullName()})
+ ld.V2MetadataService.Add(diffID, metadata.V2Metadata{Digest: ld.digest, SourceRepository: ld.repoInfo.Name.Name()})
}
func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdated bool, err error) {
@@ -343,7 +344,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
}
tagOrDigest = digested.Digest().String()
} else {
- return false, fmt.Errorf("internal error: reference has neither a tag nor a digest: %s", ref.String())
+ return false, fmt.Errorf("internal error: reference has neither a tag nor a digest: %s", reference.FamiliarString(ref))
}
if manifest == nil {
@@ -371,8 +372,8 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
// the other side speaks the v2 protocol.
p.confirmedV2 = true
- logrus.Debugf("Pulling ref from V2 registry: %s", ref.String())
- progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+p.repo.Named().Name())
+ logrus.Debugf("Pulling ref from V2 registry: %s", reference.FamiliarString(ref))
+ progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+reference.FamiliarName(p.repo.Named()))
var (
id digest.Digest
@@ -410,7 +411,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
if oldTagID == id {
return false, addDigestReference(p.config.ReferenceStore, ref, manifestDigest, id)
}
- } else if err != reference.ErrDoesNotExist {
+ } else if err != refstore.ErrDoesNotExist {
return false, err
}
@@ -802,13 +803,13 @@ func verifySchema1Manifest(signedManifest *schema1.SignedManifest, ref reference
m = &signedManifest.Manifest
if m.SchemaVersion != 1 {
- return nil, fmt.Errorf("unsupported schema version %d for %q", m.SchemaVersion, ref.String())
+ return nil, fmt.Errorf("unsupported schema version %d for %q", m.SchemaVersion, reference.FamiliarString(ref))
}
if len(m.FSLayers) != len(m.History) {
- return nil, fmt.Errorf("length of history not equal to number of layers for %q", ref.String())
+ return nil, fmt.Errorf("length of history not equal to number of layers for %q", reference.FamiliarString(ref))
}
if len(m.FSLayers) == 0 {
- return nil, fmt.Errorf("no FSLayers in manifest for %q", ref.String())
+ return nil, fmt.Errorf("no FSLayers in manifest for %q", reference.FamiliarString(ref))
}
return m, nil
}
diff --git a/distribution/pull_v2_test.go b/distribution/pull_v2_test.go
index d65653311c..df93c1ef83 100644
--- a/distribution/pull_v2_test.go
+++ b/distribution/pull_v2_test.go
@@ -9,7 +9,7 @@ import (
"testing"
"github.com/docker/distribution/manifest/schema1"
- "github.com/docker/docker/reference"
+ "github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest"
)
@@ -113,7 +113,7 @@ func TestValidateManifest(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Needs fixing on Windows")
}
- expectedDigest, err := reference.ParseNamed("repo@sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd")
+ expectedDigest, err := reference.ParseNormalizedNamed("repo@sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd")
if err != nil {
t.Fatal("could not parse reference")
}
diff --git a/distribution/push.go b/distribution/push.go
index d35bdb103e..9d5328035c 100644
--- a/distribution/push.go
+++ b/distribution/push.go
@@ -7,9 +7,9 @@ import (
"io"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"golang.org/x/net/context"
)
@@ -64,16 +64,16 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
return err
}
- endpoints, err := imagePushConfig.RegistryService.LookupPushEndpoints(repoInfo.Hostname())
+ endpoints, err := imagePushConfig.RegistryService.LookupPushEndpoints(reference.Domain(repoInfo.Name))
if err != nil {
return err
}
- progress.Messagef(imagePushConfig.ProgressOutput, "", "The push refers to a repository [%s]", repoInfo.FullName())
+ progress.Messagef(imagePushConfig.ProgressOutput, "", "The push refers to a repository [%s]", repoInfo.Name.Name())
- associations := imagePushConfig.ReferenceStore.ReferencesByName(repoInfo)
+ associations := imagePushConfig.ReferenceStore.ReferencesByName(repoInfo.Name)
if len(associations) == 0 {
- return fmt.Errorf("An image does not exist locally with the tag: %s", repoInfo.Name())
+ return fmt.Errorf("An image does not exist locally with the tag: %s", reference.FamiliarName(repoInfo.Name))
}
var (
@@ -106,7 +106,7 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
}
}
- logrus.Debugf("Trying to push %s to %s %s", repoInfo.FullName(), endpoint.URL, endpoint.Version)
+ logrus.Debugf("Trying to push %s to %s %s", repoInfo.Name.Name(), endpoint.URL, endpoint.Version)
pusher, err := NewPusher(ref, endpoint, repoInfo, imagePushConfig)
if err != nil {
@@ -135,12 +135,12 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
return err
}
- imagePushConfig.ImageEventLogger(ref.String(), repoInfo.Name(), "push")
+ imagePushConfig.ImageEventLogger(reference.FamiliarString(ref), reference.FamiliarName(repoInfo.Name), "push")
return nil
}
if lastErr == nil {
- lastErr = fmt.Errorf("no endpoints found for %s", repoInfo.FullName())
+ lastErr = fmt.Errorf("no endpoints found for %s", repoInfo.Name.Name())
}
return lastErr
}
diff --git a/distribution/push_v1.go b/distribution/push_v1.go
index 67ed3554c0..431faaf28c 100644
--- a/distribution/push_v1.go
+++ b/distribution/push_v1.go
@@ -5,6 +5,7 @@ import (
"sync"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client/transport"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/dockerversion"
@@ -14,7 +15,6 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
"golang.org/x/net/context"
@@ -356,8 +356,8 @@ func (p *v1Pusher) pushImageToEndpoint(ctx context.Context, endpoint string, ima
}
if topImage, isTopImage := img.(*v1TopImage); isTopImage {
for _, tag := range tags[topImage.imageID] {
- progress.Messagef(p.config.ProgressOutput, "", "Pushing tag for rev [%s] on {%s}", stringid.TruncateID(v1ID), endpoint+"repositories/"+p.repoInfo.RemoteName()+"/tags/"+tag)
- if err := p.session.PushRegistryTag(p.repoInfo, v1ID, tag, endpoint); err != nil {
+ progress.Messagef(p.config.ProgressOutput, "", "Pushing tag for rev [%s] on {%s}", stringid.TruncateID(v1ID), endpoint+"repositories/"+reference.Path(p.repoInfo.Name)+"/tags/"+tag)
+ if err := p.session.PushRegistryTag(p.repoInfo.Name, v1ID, tag, endpoint); err != nil {
return err
}
}
@@ -385,7 +385,7 @@ func (p *v1Pusher) pushRepository(ctx context.Context) error {
// Register all the images in a repository with the registry
// If an image is not in this list it will not be associated with the repository
- repoData, err := p.session.PushImageJSONIndex(p.repoInfo, imageIndex, false, nil)
+ repoData, err := p.session.PushImageJSONIndex(p.repoInfo.Name, imageIndex, false, nil)
if err != nil {
return err
}
@@ -395,7 +395,7 @@ func (p *v1Pusher) pushRepository(ctx context.Context) error {
return err
}
}
- _, err = p.session.PushImageJSONIndex(p.repoInfo, imageIndex, true, repoData.Endpoints)
+ _, err = p.session.PushImageJSONIndex(p.repoInfo.Name, imageIndex, true, repoData.Endpoints)
return err
}
diff --git a/distribution/push_v2.go b/distribution/push_v2.go
index f2115b39bc..d6fa8b1c88 100644
--- a/distribution/push_v2.go
+++ b/distribution/push_v2.go
@@ -15,7 +15,7 @@ import (
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/schema1"
"github.com/docker/distribution/manifest/schema2"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client"
apitypes "github.com/docker/docker/api/types"
"github.com/docker/docker/distribution/metadata"
@@ -24,7 +24,6 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
)
@@ -83,7 +82,7 @@ func (p *v2Pusher) pushV2Repository(ctx context.Context) (err error) {
if namedTagged, isNamedTagged := p.ref.(reference.NamedTagged); isNamedTagged {
imageID, err := p.config.ReferenceStore.Get(p.ref)
if err != nil {
- return fmt.Errorf("tag does not exist: %s", p.ref.String())
+ return fmt.Errorf("tag does not exist: %s", reference.FamiliarString(p.ref))
}
return p.pushV2Tag(ctx, namedTagged, imageID)
@@ -105,23 +104,23 @@ func (p *v2Pusher) pushV2Repository(ctx context.Context) (err error) {
}
if pushed == 0 {
- return fmt.Errorf("no tags to push for %s", p.repoInfo.Name())
+ return fmt.Errorf("no tags to push for %s", reference.FamiliarName(p.repoInfo.Name))
}
return nil
}
func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id digest.Digest) error {
- logrus.Debugf("Pushing repository: %s", ref.String())
+ logrus.Debugf("Pushing repository: %s", reference.FamiliarString(ref))
imgConfig, err := p.config.ImageStore.Get(id)
if err != nil {
- return fmt.Errorf("could not find image from tag %s: %v", ref.String(), err)
+ return fmt.Errorf("could not find image from tag %s: %v", reference.FamiliarString(ref), err)
}
rootfs, err := p.config.ImageStore.RootFSFromConfig(imgConfig)
if err != nil {
- return fmt.Errorf("unable to get rootfs for image %s: %s", ref.String(), err)
+ return fmt.Errorf("unable to get rootfs for image %s: %s", reference.FamiliarString(ref), err)
}
l, err := p.config.LayerStore.Get(rootfs.ChainID())
@@ -140,7 +139,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id
descriptorTemplate := v2PushDescriptor{
v2MetadataService: p.v2MetadataService,
hmacKey: hmacKey,
- repoInfo: p.repoInfo,
+ repoInfo: p.repoInfo.Name,
ref: p.ref,
repo: p.repo,
pushState: &p.pushState,
@@ -181,7 +180,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id
logrus.Warnf("failed to upload schema2 manifest: %v - falling back to schema1", err)
- manifestRef, err := distreference.WithTag(p.repo.Named(), ref.Tag())
+ manifestRef, err := reference.WithTag(p.repo.Named(), ref.Tag())
if err != nil {
return err
}
@@ -248,7 +247,7 @@ type v2PushDescriptor struct {
}
func (pd *v2PushDescriptor) Key() string {
- return "v2push:" + pd.ref.FullName() + " " + pd.layer.DiffID().String()
+ return "v2push:" + pd.ref.Name() + " " + pd.layer.DiffID().String()
}
func (pd *v2PushDescriptor) ID() string {
@@ -304,23 +303,22 @@ func (pd *v2PushDescriptor) Upload(ctx context.Context, progressOutput progress.
createOpts := []distribution.BlobCreateOption{}
if len(mountCandidate.SourceRepository) > 0 {
- namedRef, err := reference.WithName(mountCandidate.SourceRepository)
+ namedRef, err := reference.ParseNormalizedNamed(mountCandidate.SourceRepository)
if err != nil {
- logrus.Errorf("failed to parse source repository reference %v: %v", namedRef.String(), err)
+ logrus.Errorf("failed to parse source repository reference %v: %v", reference.FamiliarString(namedRef), err)
pd.v2MetadataService.Remove(mountCandidate)
continue
}
- // TODO (brianbland): We need to construct a reference where the Name is
- // only the full remote name, so clean this up when distribution has a
- // richer reference package
- remoteRef, err := distreference.WithName(namedRef.RemoteName())
+ // Candidates are always under same domain, create remote reference
+ // with only path to set mount from with
+ remoteRef, err := reference.WithName(reference.Path(namedRef))
if err != nil {
- logrus.Errorf("failed to make remote reference out of %q: %v", namedRef.RemoteName(), namedRef.RemoteName())
+ logrus.Errorf("failed to make remote reference out of %q: %v", reference.Path(namedRef), err)
continue
}
- canonicalRef, err := distreference.WithDigest(distreference.TrimNamed(remoteRef), mountCandidate.Digest)
+ canonicalRef, err := reference.WithDigest(reference.TrimNamed(remoteRef), mountCandidate.Digest)
if err != nil {
logrus.Errorf("failed to make canonical reference: %v", err)
continue
@@ -347,7 +345,7 @@ func (pd *v2PushDescriptor) Upload(ctx context.Context, progressOutput progress.
// Cache mapping from this layer's DiffID to the blobsum
if err := pd.v2MetadataService.TagAndAdd(diffID, pd.hmacKey, metadata.V2Metadata{
Digest: err.Descriptor.Digest,
- SourceRepository: pd.repoInfo.FullName(),
+ SourceRepository: pd.repoInfo.Name(),
}); err != nil {
return distribution.Descriptor{}, xfer.DoNotRetry{Err: err}
}
@@ -455,7 +453,7 @@ func (pd *v2PushDescriptor) uploadUsingSession(
// Cache mapping from this layer's DiffID to the blobsum
if err := pd.v2MetadataService.TagAndAdd(diffID, pd.hmacKey, metadata.V2Metadata{
Digest: pushDigest,
- SourceRepository: pd.repoInfo.FullName(),
+ SourceRepository: pd.repoInfo.Name(),
}); err != nil {
return distribution.Descriptor{}, xfer.DoNotRetry{Err: err}
}
@@ -490,7 +488,7 @@ func (pd *v2PushDescriptor) layerAlreadyExists(
// filter the metadata
candidates := []metadata.V2Metadata{}
for _, meta := range v2Metadata {
- if len(meta.SourceRepository) > 0 && !checkOtherRepositories && meta.SourceRepository != pd.repoInfo.FullName() {
+ if len(meta.SourceRepository) > 0 && !checkOtherRepositories && meta.SourceRepository != pd.repoInfo.Name() {
continue
}
candidates = append(candidates, meta)
@@ -521,16 +519,16 @@ func (pd *v2PushDescriptor) layerAlreadyExists(
attempts:
for _, dgst := range layerDigests {
meta := digestToMetadata[dgst]
- logrus.Debugf("Checking for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.FullName())
+ logrus.Debugf("Checking for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.Name())
desc, err = pd.repo.Blobs(ctx).Stat(ctx, dgst)
pd.checkedDigests[meta.Digest] = struct{}{}
switch err {
case nil:
- if m, ok := digestToMetadata[desc.Digest]; !ok || m.SourceRepository != pd.repoInfo.FullName() || !metadata.CheckV2MetadataHMAC(m, pd.hmacKey) {
+ if m, ok := digestToMetadata[desc.Digest]; !ok || m.SourceRepository != pd.repoInfo.Name() || !metadata.CheckV2MetadataHMAC(m, pd.hmacKey) {
// cache mapping from this layer's DiffID to the blobsum
if err := pd.v2MetadataService.TagAndAdd(diffID, pd.hmacKey, metadata.V2Metadata{
Digest: desc.Digest,
- SourceRepository: pd.repoInfo.FullName(),
+ SourceRepository: pd.repoInfo.Name(),
}); err != nil {
return distribution.Descriptor{}, false, xfer.DoNotRetry{Err: err}
}
@@ -539,12 +537,12 @@ attempts:
exists = true
break attempts
case distribution.ErrBlobUnknown:
- if meta.SourceRepository == pd.repoInfo.FullName() {
+ if meta.SourceRepository == pd.repoInfo.Name() {
// remove the mapping to the target repository
pd.v2MetadataService.Remove(*meta)
}
default:
- logrus.WithError(err).Debugf("Failed to check for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.FullName())
+ logrus.WithError(err).Debugf("Failed to check for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.Name())
}
}
@@ -598,11 +596,11 @@ func getRepositoryMountCandidates(
candidates := []metadata.V2Metadata{}
for _, meta := range v2Metadata {
sourceRepo, err := reference.ParseNamed(meta.SourceRepository)
- if err != nil || repoInfo.Hostname() != sourceRepo.Hostname() {
+ if err != nil || reference.Domain(repoInfo) != reference.Domain(sourceRepo) {
continue
}
// target repository is not a viable candidate
- if meta.SourceRepository == repoInfo.FullName() {
+ if meta.SourceRepository == repoInfo.Name() {
continue
}
candidates = append(candidates, meta)
@@ -653,7 +651,7 @@ func sortV2MetadataByLikenessAndAge(repoInfo reference.Named, hmacKey []byte, ma
sort.Stable(byLikeness{
arr: marr,
hmacKey: hmacKey,
- pathComponents: getPathComponents(repoInfo.FullName()),
+ pathComponents: getPathComponents(repoInfo.Name()),
})
}
@@ -670,11 +668,6 @@ func numOfMatchingPathComponents(pth string, matchComponents []string) int {
}
func getPathComponents(path string) []string {
- // make sure to add docker.io/ prefix to the path
- named, err := reference.ParseNamed(path)
- if err == nil {
- path = named.FullName()
- }
return strings.Split(path, "/")
}
diff --git a/distribution/push_v2_test.go b/distribution/push_v2_test.go
index 7e9f4166f1..e8e2b1af25 100644
--- a/distribution/push_v2_test.go
+++ b/distribution/push_v2_test.go
@@ -8,11 +8,10 @@ import (
"github.com/docker/distribution"
"github.com/docker/distribution/context"
"github.com/docker/distribution/manifest/schema2"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/progress"
- "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
)
@@ -43,8 +42,8 @@ func TestGetRepositoryMountCandidates(t *testing.T) {
name: "one item matching",
targetRepo: "busybox",
maxCandidates: -1,
- metadata: []metadata.V2Metadata{taggedMetadata("hash", "1", "hello-world")},
- candidates: []metadata.V2Metadata{taggedMetadata("hash", "1", "hello-world")},
+ metadata: []metadata.V2Metadata{taggedMetadata("hash", "1", "docker.io/library/hello-world")},
+ candidates: []metadata.V2Metadata{taggedMetadata("hash", "1", "docker.io/library/hello-world")},
},
{
name: "allow missing SourceRepository",
@@ -63,13 +62,13 @@ func TestGetRepositoryMountCandidates(t *testing.T) {
maxCandidates: -1,
metadata: []metadata.V2Metadata{
{Digest: digest.Digest("1"), SourceRepository: "docker.io/user/foo"},
- {Digest: digest.Digest("3"), SourceRepository: "user/bar"},
- {Digest: digest.Digest("2"), SourceRepository: "app"},
+ {Digest: digest.Digest("3"), SourceRepository: "docker.io/user/bar"},
+ {Digest: digest.Digest("2"), SourceRepository: "docker.io/library/app"},
},
candidates: []metadata.V2Metadata{
- {Digest: digest.Digest("3"), SourceRepository: "user/bar"},
+ {Digest: digest.Digest("3"), SourceRepository: "docker.io/user/bar"},
{Digest: digest.Digest("1"), SourceRepository: "docker.io/user/foo"},
- {Digest: digest.Digest("2"), SourceRepository: "app"},
+ {Digest: digest.Digest("2"), SourceRepository: "docker.io/library/app"},
},
},
{
@@ -78,10 +77,10 @@ func TestGetRepositoryMountCandidates(t *testing.T) {
targetRepo: "127.0.0.1/foo/bar",
maxCandidates: -1,
metadata: []metadata.V2Metadata{
- taggedMetadata("hash", "1", "hello-world"),
+ taggedMetadata("hash", "1", "docker.io/library/hello-world"),
taggedMetadata("efgh", "2", "127.0.0.1/hello-world"),
- taggedMetadata("abcd", "3", "busybox"),
- taggedMetadata("hash", "4", "busybox"),
+ taggedMetadata("abcd", "3", "docker.io/library/busybox"),
+ taggedMetadata("hash", "4", "docker.io/library/busybox"),
taggedMetadata("hash", "5", "127.0.0.1/foo"),
taggedMetadata("hash", "6", "127.0.0.1/bar"),
taggedMetadata("efgh", "7", "127.0.0.1/foo/bar"),
@@ -105,23 +104,25 @@ func TestGetRepositoryMountCandidates(t *testing.T) {
targetRepo: "user/app",
maxCandidates: 3,
metadata: []metadata.V2Metadata{
- taggedMetadata("abcd", "1", "user/app1"),
- taggedMetadata("abcd", "2", "user/app/base"),
- taggedMetadata("hash", "3", "user/app"),
+ taggedMetadata("abcd", "1", "docker.io/user/app1"),
+ taggedMetadata("abcd", "2", "docker.io/user/app/base"),
+ taggedMetadata("hash", "3", "docker.io/user/app"),
taggedMetadata("abcd", "4", "127.0.0.1/user/app"),
- taggedMetadata("hash", "5", "user/foo"),
- taggedMetadata("hash", "6", "app/bar"),
+ taggedMetadata("hash", "5", "docker.io/user/foo"),
+ taggedMetadata("hash", "6", "docker.io/app/bar"),
},
candidates: []metadata.V2Metadata{
// first by matching hash
- taggedMetadata("abcd", "2", "user/app/base"),
- taggedMetadata("abcd", "1", "user/app1"),
+ taggedMetadata("abcd", "2", "docker.io/user/app/base"),
+ taggedMetadata("abcd", "1", "docker.io/user/app1"),
// then by longest matching prefix
- taggedMetadata("hash", "3", "user/app"),
+ // "docker.io/usr/app" is excluded since candidates must
+ // be from a different repository
+ taggedMetadata("hash", "5", "docker.io/user/foo"),
},
},
} {
- repoInfo, err := reference.ParseNamed(tc.targetRepo)
+ repoInfo, err := reference.ParseNormalizedNamed(tc.targetRepo)
if err != nil {
t.Fatalf("[%s] failed to parse reference name: %v", tc.name, err)
}
@@ -204,10 +205,13 @@ func TestLayerAlreadyExists(t *testing.T) {
{Digest: digest.Digest("apple"), SourceRepository: "docker.io/library/hello-world"},
{Digest: digest.Digest("orange"), SourceRepository: "docker.io/busybox/subapp"},
{Digest: digest.Digest("pear"), SourceRepository: "docker.io/busybox"},
- {Digest: digest.Digest("plum"), SourceRepository: "busybox"},
+ {Digest: digest.Digest("plum"), SourceRepository: "docker.io/library/busybox"},
{Digest: digest.Digest("banana"), SourceRepository: "127.0.0.1/busybox"},
},
- expectedRequests: []string{"plum", "pear", "apple", "orange", "banana"},
+ expectedRequests: []string{"plum", "apple", "pear", "orange", "banana"},
+ expectedRemovals: []metadata.V2Metadata{
+ {Digest: digest.Digest("plum"), SourceRepository: "docker.io/library/busybox"},
+ },
},
{
name: "find existing blob",
@@ -374,7 +378,7 @@ func TestLayerAlreadyExists(t *testing.T) {
},
},
} {
- repoInfo, err := reference.ParseNamed(tc.targetRepo)
+ repoInfo, err := reference.ParseNormalizedNamed(tc.targetRepo)
if err != nil {
t.Fatalf("[%s] failed to parse reference name: %v", tc.name, err)
}
@@ -476,7 +480,7 @@ type mockRepo struct {
var _ distribution.Repository = &mockRepo{}
-func (m *mockRepo) Named() distreference.Named {
+func (m *mockRepo) Named() reference.Named {
m.t.Fatalf("Named() not implemented")
return nil
}
diff --git a/distribution/registry.go b/distribution/registry.go
index 95e181ded8..bce270a5ed 100644
--- a/distribution/registry.go
+++ b/distribution/registry.go
@@ -8,7 +8,7 @@ import (
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/schema2"
- distreference "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/distribution/registry/client/transport"
@@ -55,10 +55,10 @@ func init() {
// providing timeout settings and authentication support, and also verifies the
// remote API version.
func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, endpoint registry.APIEndpoint, metaHeaders http.Header, authConfig *types.AuthConfig, actions ...string) (repo distribution.Repository, foundVersion bool, err error) {
- repoName := repoInfo.FullName()
+ repoName := repoInfo.Name.Name()
// If endpoint does not support CanonicalName, use the RemoteName instead
if endpoint.TrimHostname {
- repoName = repoInfo.RemoteName()
+ repoName = reference.Path(repoInfo.Name)
}
direct := &net.Dialer{
@@ -122,7 +122,7 @@ func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, end
}
tr := transport.NewTransport(base, modifiers...)
- repoNameRef, err := distreference.ParseNamed(repoName)
+ repoNameRef, err := reference.WithName(repoName)
if err != nil {
return nil, foundVersion, fallbackError{
err: err,
diff --git a/distribution/registry_unit_test.go b/distribution/registry_unit_test.go
index 75d08f4866..ebe6ecad97 100644
--- a/distribution/registry_unit_test.go
+++ b/distribution/registry_unit_test.go
@@ -12,11 +12,11 @@ import (
"testing"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/stringid"
- "github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"golang.org/x/net/context"
)
@@ -61,9 +61,9 @@ func testTokenPassThru(t *testing.T, ts *httptest.Server) {
TrimHostname: false,
TLSConfig: nil,
}
- n, _ := reference.ParseNamed("testremotename")
+ n, _ := reference.ParseNormalizedNamed("testremotename")
repoInfo := &registry.RepositoryInfo{
- Named: n,
+ Name: n,
Index: &registrytypes.IndexInfo{
Name: "testrepo",
Mirrors: nil,
diff --git a/image/tarexport/load.go b/image/tarexport/load.go
index 0ef07f8e16..cdd377ab90 100644
--- a/image/tarexport/load.go
+++ b/image/tarexport/load.go
@@ -11,6 +11,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/distribution"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/image"
"github.com/docker/docker/image/v1"
"github.com/docker/docker/layer"
@@ -21,7 +22,6 @@ import (
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/system"
- "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
)
@@ -117,7 +117,7 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
imageRefCount = 0
for _, repoTag := range m.RepoTags {
- named, err := reference.ParseNamed(repoTag)
+ named, err := reference.ParseNormalizedNamed(repoTag)
if err != nil {
return err
}
@@ -126,7 +126,7 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
return fmt.Errorf("invalid tag %q", repoTag)
}
l.setLoadedTag(ref, imgID.Digest(), outStream)
- outStream.Write([]byte(fmt.Sprintf("Loaded image: %s\n", ref)))
+ outStream.Write([]byte(fmt.Sprintf("Loaded image: %s\n", reference.FamiliarString(ref))))
imageRefCount++
}
@@ -201,7 +201,7 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string,
func (l *tarexporter) setLoadedTag(ref reference.NamedTagged, imgID digest.Digest, outStream io.Writer) error {
if prevID, err := l.rs.Get(ref); err == nil && prevID != imgID {
- fmt.Fprintf(outStream, "The image %s already exists, renaming the old one with ID %s to empty string\n", ref.String(), string(prevID)) // todo: this message is wrong in case of multiple tags
+ fmt.Fprintf(outStream, "The image %s already exists, renaming the old one with ID %s to empty string\n", reference.FamiliarString(ref), string(prevID)) // todo: this message is wrong in case of multiple tags
}
if err := l.rs.AddTag(ref, imgID, true); err != nil {
@@ -249,7 +249,7 @@ func (l *tarexporter) legacyLoad(tmpDir string, outStream io.Writer, progressOut
if !ok {
return fmt.Errorf("invalid target ID: %v", oldID)
}
- named, err := reference.WithName(name)
+ named, err := reference.ParseNormalizedNamed(name)
if err != nil {
return err
}
diff --git a/image/tarexport/save.go b/image/tarexport/save.go
index bab7a9611f..8d33a58724 100644
--- a/image/tarexport/save.go
+++ b/image/tarexport/save.go
@@ -10,12 +10,12 @@ import (
"time"
"github.com/docker/distribution"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/image"
"github.com/docker/docker/image/v1"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/system"
- "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)
@@ -51,16 +51,12 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
}
if ref != nil {
- var tagged reference.NamedTagged
if _, ok := ref.(reference.Canonical); ok {
return
}
- var ok bool
- if tagged, ok = ref.(reference.NamedTagged); !ok {
- var err error
- if tagged, err = reference.WithTag(ref, reference.DefaultTag); err != nil {
- return
- }
+ tagged, ok := reference.TagNameOnly(ref).(reference.NamedTagged)
+ if !ok {
+ return
}
for _, t := range imgDescr[id].refs {
@@ -73,19 +69,26 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
}
for _, name := range names {
- id, ref, err := reference.ParseIDOrReference(name)
+ ref, err := reference.ParseAnyReference(name)
if err != nil {
return nil, err
}
- if id != "" {
- _, err := l.is.Get(image.IDFromDigest(id))
- if err != nil {
- return nil, err
+ namedRef, ok := ref.(reference.Named)
+ if !ok {
+ // Check if digest ID reference
+ if digested, ok := ref.(reference.Digested); ok {
+ id := image.IDFromDigest(digested.Digest())
+ _, err := l.is.Get(id)
+ if err != nil {
+ return nil, err
+ }
+ addAssoc(id, nil)
+ continue
}
- addAssoc(image.IDFromDigest(id), nil)
- continue
+ return nil, errors.Errorf("invalid reference: %v", name)
}
- if ref.Name() == string(digest.Canonical) {
+
+ if reference.FamiliarName(namedRef) == string(digest.Canonical) {
imgID, err := l.is.Search(name)
if err != nil {
return nil, err
@@ -93,8 +96,8 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
addAssoc(imgID, nil)
continue
}
- if reference.IsNameOnly(ref) {
- assocs := l.rs.ReferencesByName(ref)
+ if reference.IsNameOnly(namedRef) {
+ assocs := l.rs.ReferencesByName(namedRef)
for _, assoc := range assocs {
addAssoc(image.IDFromDigest(assoc.ID), assoc.Ref)
}
@@ -107,11 +110,11 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
}
continue
}
- id, err = l.rs.Get(ref)
+ id, err := l.rs.Get(namedRef)
if err != nil {
return nil, err
}
- addAssoc(image.IDFromDigest(id), ref)
+ addAssoc(image.IDFromDigest(id), namedRef)
}
return imgDescr, nil
@@ -144,11 +147,12 @@ func (s *saveSession) save(outStream io.Writer) error {
var layers []string
for _, ref := range imageDescr.refs {
- if _, ok := reposLegacy[ref.Name()]; !ok {
- reposLegacy[ref.Name()] = make(map[string]string)
+ familiarName := reference.FamiliarName(ref)
+ if _, ok := reposLegacy[familiarName]; !ok {
+ reposLegacy[familiarName] = make(map[string]string)
}
- reposLegacy[ref.Name()][ref.Tag()] = imageDescr.layers[len(imageDescr.layers)-1]
- repoTags = append(repoTags, ref.String())
+ reposLegacy[familiarName][ref.Tag()] = imageDescr.layers[len(imageDescr.layers)-1]
+ repoTags = append(repoTags, reference.FamiliarString(ref))
}
for _, l := range imageDescr.layers {
diff --git a/image/tarexport/tarexport.go b/image/tarexport/tarexport.go
index a5229e555b..f7fab74f53 100644
--- a/image/tarexport/tarexport.go
+++ b/image/tarexport/tarexport.go
@@ -4,7 +4,7 @@ import (
"github.com/docker/distribution"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
)
const (
@@ -26,7 +26,7 @@ type manifestItem struct {
type tarexporter struct {
is image.Store
ls layer.Store
- rs reference.Store
+ rs refstore.Store
loggerImgEvent LogImageEvent
}
@@ -37,7 +37,7 @@ type LogImageEvent interface {
}
// NewTarExporter returns new Exporter for tar packages
-func NewTarExporter(is image.Store, ls layer.Store, rs reference.Store, loggerImgEvent LogImageEvent) image.Exporter {
+func NewTarExporter(is image.Store, ls layer.Store, rs refstore.Store, loggerImgEvent LogImageEvent) image.Exporter {
return &tarexporter{
is: is,
ls: ls,
diff --git a/integration-cli/docker_cli_images_test.go b/integration-cli/docker_cli_images_test.go
index 61c700362e..4bcc04d67d 100644
--- a/integration-cli/docker_cli_images_test.go
+++ b/integration-cli/docker_cli_images_test.go
@@ -335,7 +335,7 @@ func (s *DockerSuite) TestImagesFormat(c *check.C) {
expected := []string{"myimage", "myimage"}
var names []string
names = append(names, lines...)
- c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
+ c.Assert(names, checker.DeepEquals, expected, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
}
// ImagesDefaultFormatAndQuiet
diff --git a/migrate/v1/migratev1.go b/migrate/v1/migratev1.go
index c9d8108a25..3cb8828915 100644
--- a/migrate/v1/migratev1.go
+++ b/migrate/v1/migratev1.go
@@ -14,12 +14,13 @@ import (
"encoding/json"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/image"
imagev1 "github.com/docker/docker/image/v1"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/ioutils"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
)
@@ -56,7 +57,7 @@ var (
// Migrate takes an old graph directory and transforms the metadata into the
// new format.
-func Migrate(root, driverName string, ls layer.Store, is image.Store, rs reference.Store, ms metadata.Store) error {
+func Migrate(root, driverName string, ls layer.Store, is image.Store, rs refstore.Store, ms metadata.Store) error {
graphDir := filepath.Join(root, graphDirName)
if _, err := os.Lstat(graphDir); os.IsNotExist(err) {
return nil
@@ -322,11 +323,15 @@ func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image
for name, repo := range repos.Repositories {
for tag, id := range repo {
if strongID, exists := mappings[id]; exists {
- ref, err := reference.WithName(name)
+ ref, err := reference.ParseNormalizedNamed(name)
if err != nil {
logrus.Errorf("migrate tags: invalid name %q, %q", name, err)
continue
}
+ if !reference.IsNameOnly(ref) {
+ logrus.Errorf("migrate tags: invalid name %q, unexpected tag or digest", name)
+ continue
+ }
if dgst, err := digest.Parse(tag); err == nil {
canonical, err := reference.WithDigest(reference.TrimNamed(ref), dgst)
if err != nil {
@@ -334,7 +339,7 @@ func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image
continue
}
if err := rs.AddDigest(canonical, strongID.Digest(), false); err != nil {
- logrus.Errorf("can't migrate digest %q for %q, err: %q", ref.String(), strongID, err)
+ logrus.Errorf("can't migrate digest %q for %q, err: %q", reference.FamiliarString(ref), strongID, err)
}
} else {
tagRef, err := reference.WithTag(ref, tag)
@@ -343,7 +348,7 @@ func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image
continue
}
if err := rs.AddTag(tagRef, strongID.Digest(), false); err != nil {
- logrus.Errorf("can't migrate tag %q for %q, err: %q", ref.String(), strongID, err)
+ logrus.Errorf("can't migrate tag %q for %q, err: %q", reference.FamiliarString(ref), strongID, err)
}
}
logrus.Infof("migrated tag %s:%s to point to %s", name, tag, strongID)
diff --git a/migrate/v1/migratev1_test.go b/migrate/v1/migratev1_test.go
index 796c07814a..55898f12b4 100644
--- a/migrate/v1/migratev1_test.go
+++ b/migrate/v1/migratev1_test.go
@@ -13,10 +13,10 @@ import (
"runtime"
"testing"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/distribution/metadata"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
- "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
)
@@ -40,9 +40,9 @@ func TestMigrateRefs(t *testing.T) {
}
expected := map[string]string{
- "busybox:latest": "sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9",
- "busybox@sha256:16a2a52884c2a9481ed267c2d46483eac7693b813a63132368ab098a71303f8a": "sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9",
- "registry:2": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
+ "docker.io/library/busybox:latest": "sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9",
+ "docker.io/library/busybox@sha256:16a2a52884c2a9481ed267c2d46483eac7693b813a63132368ab098a71303f8a": "sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9",
+ "docker.io/library/registry:2": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
}
if !reflect.DeepEqual(expected, ta.refs) {
diff --git a/plugin/backend_linux.go b/plugin/backend_linux.go
index e88aad86f3..ddd0dd5986 100644
--- a/plugin/backend_linux.go
+++ b/plugin/backend_linux.go
@@ -18,6 +18,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/manifest/schema2"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/distribution"
@@ -30,7 +31,7 @@ import (
"github.com/docker/docker/pkg/pools"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/plugin/v2"
- "github.com/docker/docker/reference"
+ refstore "github.com/docker/docker/reference"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"golang.org/x/net/context"
@@ -232,11 +233,11 @@ func (pm *Manager) Upgrade(ctx context.Context, ref reference.Named, name string
defer pm.muGC.RUnlock()
// revalidate because Pull is public
- nameref, err := reference.ParseNamed(name)
+ nameref, err := reference.ParseNormalizedNamed(name)
if err != nil {
return errors.Wrapf(err, "failed to parse %q", name)
}
- name = reference.WithDefaultTag(nameref).String()
+ name = reference.FamiliarString(reference.TagNameOnly(nameref))
tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs")
defer os.RemoveAll(tmpRootFSDir)
@@ -277,11 +278,11 @@ func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, m
defer pm.muGC.RUnlock()
// revalidate because Pull is public
- nameref, err := reference.ParseNamed(name)
+ nameref, err := reference.ParseNormalizedNamed(name)
if err != nil {
return errors.Wrapf(err, "failed to parse %q", name)
}
- name = reference.WithDefaultTag(nameref).String()
+ name = reference.FamiliarString(reference.TagNameOnly(nameref))
if err := pm.config.Store.validateName(name); err != nil {
return err
@@ -370,7 +371,7 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header
return err
}
- ref, err := reference.ParseNamed(p.Name())
+ ref, err := reference.ParseNormalizedNamed(p.Name())
if err != nil {
return errors.Wrapf(err, "plugin has invalid name %v for push", p.Name())
}
@@ -448,8 +449,8 @@ func (r *pluginReference) References(id digest.Digest) []reference.Named {
return []reference.Named{r.name}
}
-func (r *pluginReference) ReferencesByName(ref reference.Named) []reference.Association {
- return []reference.Association{
+func (r *pluginReference) ReferencesByName(ref reference.Named) []refstore.Association {
+ return []refstore.Association{
{
Ref: r.name,
ID: r.pluginID,
@@ -459,7 +460,7 @@ func (r *pluginReference) ReferencesByName(ref reference.Named) []reference.Asso
func (r *pluginReference) Get(ref reference.Named) (digest.Digest, error) {
if r.name.String() != ref.String() {
- return digest.Digest(""), reference.ErrDoesNotExist
+ return digest.Digest(""), refstore.ErrDoesNotExist
}
return r.pluginID, nil
}
@@ -664,15 +665,14 @@ func (pm *Manager) CreateFromContext(ctx context.Context, tarCtx io.ReadCloser,
pm.muGC.RLock()
defer pm.muGC.RUnlock()
- ref, err := reference.ParseNamed(options.RepoName)
+ ref, err := reference.ParseNormalizedNamed(options.RepoName)
if err != nil {
return errors.Wrapf(err, "failed to parse reference %v", options.RepoName)
}
if _, ok := ref.(reference.Canonical); ok {
return errors.Errorf("canonical references are not permitted")
}
- taggedRef := reference.WithDefaultTag(ref)
- name := taggedRef.String()
+ name := reference.FamiliarString(reference.TagNameOnly(ref))
if err := pm.config.Store.validateName(name); err != nil { // fast check, real check is in createPlugin()
return err
@@ -754,7 +754,7 @@ func (pm *Manager) CreateFromContext(ctx context.Context, tarCtx io.ReadCloser,
if err != nil {
return err
}
- p.PluginObj.PluginReference = taggedRef.String()
+ p.PluginObj.PluginReference = name
pm.config.LogPluginEvent(p.PluginObj.ID, name, "create")
diff --git a/plugin/backend_unsupported.go b/plugin/backend_unsupported.go
index 35feb5cdca..2d4850eeba 100644
--- a/plugin/backend_unsupported.go
+++ b/plugin/backend_unsupported.go
@@ -7,9 +7,9 @@ import (
"io"
"net/http"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/reference"
"golang.org/x/net/context"
)
diff --git a/plugin/store.go b/plugin/store.go
index ab60bff547..244522e10a 100644
--- a/plugin/store.go
+++ b/plugin/store.go
@@ -5,10 +5,10 @@ import (
"strings"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/plugins"
"github.com/docker/docker/plugin/v2"
- "github.com/docker/docker/reference"
"github.com/pkg/errors"
)
@@ -230,19 +230,19 @@ func (ps *Store) resolvePluginID(idOrName string) (string, error) {
return idOrName, nil
}
- ref, err := reference.ParseNamed(idOrName)
+ ref, err := reference.ParseNormalizedNamed(idOrName)
if err != nil {
return "", errors.WithStack(ErrNotFound(idOrName))
}
if _, ok := ref.(reference.Canonical); ok {
- logrus.Warnf("canonical references cannot be resolved: %v", ref.String())
+ logrus.Warnf("canonical references cannot be resolved: %v", reference.FamiliarString(ref))
return "", errors.WithStack(ErrNotFound(idOrName))
}
- fullRef := reference.WithDefaultTag(ref)
+ ref = reference.TagNameOnly(ref)
for _, p := range ps.plugins {
- if p.PluginObj.Name == fullRef.String() {
+ if p.PluginObj.Name == reference.FamiliarString(ref) {
return p.PluginObj.ID, nil
}
}
diff --git a/reference/reference.go b/reference/reference.go
deleted file mode 100644
index e6e070cb8c..0000000000
--- a/reference/reference.go
+++ /dev/null
@@ -1,194 +0,0 @@
-package reference
-
-import (
- "fmt"
-
- distreference "github.com/docker/distribution/reference"
- "github.com/docker/docker/pkg/stringid"
- "github.com/opencontainers/go-digest"
- "github.com/pkg/errors"
-)
-
-const (
- // DefaultTag defines the default tag used when performing images related actions and no tag or digest is specified
- DefaultTag = "latest"
- // DefaultHostname is the default built-in hostname
- DefaultHostname = "docker.io"
- // LegacyDefaultHostname is automatically converted to DefaultHostname
- LegacyDefaultHostname = "index.docker.io"
- // DefaultRepoPrefix is the prefix used for default repositories in default host
- DefaultRepoPrefix = "library/"
-)
-
-// Named is an object with a full name
-type Named interface {
- // Name returns normalized repository name, like "ubuntu".
- Name() string
- // String returns full reference, like "ubuntu@sha256:abcdef..."
- String() string
- // FullName returns full repository name with hostname, like "docker.io/library/ubuntu"
- FullName() string
- // Hostname returns hostname for the reference, like "docker.io"
- Hostname() string
- // RemoteName returns the repository component of the full name, like "library/ubuntu"
- RemoteName() string
-}
-
-// NamedTagged is an object including a name and tag.
-type NamedTagged interface {
- Named
- Tag() string
-}
-
-// Canonical reference is an object with a fully unique
-// name including a name with hostname and digest
-type Canonical interface {
- Named
- Digest() digest.Digest
-}
-
-// ParseNamed parses s and returns a syntactically valid reference implementing
-// the Named interface. The reference must have a name, otherwise an error is
-// returned.
-// If an error was encountered it is returned, along with a nil Reference.
-func ParseNamed(s string) (Named, error) {
- named, err := distreference.ParseNormalizedNamed(s)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to parse reference %q", s)
- }
- if err := validateName(distreference.FamiliarName(named)); err != nil {
- return nil, err
- }
-
- // Ensure returned reference cannot have tag and digest
- if canonical, isCanonical := named.(distreference.Canonical); isCanonical {
- r, err := distreference.WithDigest(distreference.TrimNamed(named), canonical.Digest())
- if err != nil {
- return nil, err
- }
- return &canonicalRef{namedRef{r}}, nil
- }
- if tagged, isTagged := named.(distreference.NamedTagged); isTagged {
- r, err := distreference.WithTag(distreference.TrimNamed(named), tagged.Tag())
- if err != nil {
- return nil, err
- }
- return &taggedRef{namedRef{r}}, nil
- }
-
- return &namedRef{named}, nil
-}
-
-// TrimNamed removes any tag or digest from the named reference
-func TrimNamed(ref Named) Named {
- return &namedRef{distreference.TrimNamed(ref)}
-}
-
-// WithName returns a named object representing the given string. If the input
-// is invalid ErrReferenceInvalidFormat will be returned.
-func WithName(name string) (Named, error) {
- r, err := distreference.ParseNormalizedNamed(name)
- if err != nil {
- return nil, err
- }
- if err := validateName(distreference.FamiliarName(r)); err != nil {
- return nil, err
- }
- if !distreference.IsNameOnly(r) {
- return nil, distreference.ErrReferenceInvalidFormat
- }
- return &namedRef{r}, nil
-}
-
-// WithTag combines the name from "name" and the tag from "tag" to form a
-// reference incorporating both the name and the tag.
-func WithTag(name Named, tag string) (NamedTagged, error) {
- r, err := distreference.WithTag(name, tag)
- if err != nil {
- return nil, err
- }
- return &taggedRef{namedRef{r}}, nil
-}
-
-// WithDigest combines the name from "name" and the digest from "digest" to form
-// a reference incorporating both the name and the digest.
-func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
- r, err := distreference.WithDigest(name, digest)
- if err != nil {
- return nil, err
- }
- return &canonicalRef{namedRef{r}}, nil
-}
-
-type namedRef struct {
- distreference.Named
-}
-type taggedRef struct {
- namedRef
-}
-type canonicalRef struct {
- namedRef
-}
-
-func (r *namedRef) Name() string {
- return distreference.FamiliarName(r.Named)
-}
-
-func (r *namedRef) String() string {
- return distreference.FamiliarString(r.Named)
-}
-
-func (r *namedRef) FullName() string {
- return r.Named.Name()
-}
-func (r *namedRef) Hostname() string {
- return distreference.Domain(r.Named)
-}
-func (r *namedRef) RemoteName() string {
- return distreference.Path(r.Named)
-}
-func (r *taggedRef) Tag() string {
- return r.namedRef.Named.(distreference.NamedTagged).Tag()
-}
-func (r *canonicalRef) Digest() digest.Digest {
- return r.namedRef.Named.(distreference.Canonical).Digest()
-}
-
-// WithDefaultTag adds a default tag to a reference if it only has a repo name.
-func WithDefaultTag(ref Named) Named {
- if IsNameOnly(ref) {
- ref, _ = WithTag(ref, DefaultTag)
- }
- return ref
-}
-
-// IsNameOnly returns true if reference only contains a repo name.
-func IsNameOnly(ref Named) bool {
- if _, ok := ref.(NamedTagged); ok {
- return false
- }
- if _, ok := ref.(Canonical); ok {
- return false
- }
- return true
-}
-
-// ParseIDOrReference parses string for an image ID or a reference. ID can be
-// without a default prefix.
-func ParseIDOrReference(idOrRef string) (digest.Digest, Named, error) {
- if err := stringid.ValidateID(idOrRef); err == nil {
- idOrRef = "sha256:" + idOrRef
- }
- if dgst, err := digest.Parse(idOrRef); err == nil {
- return dgst, nil, nil
- }
- ref, err := ParseNamed(idOrRef)
- return "", ref, err
-}
-
-func validateName(name string) error {
- if err := stringid.ValidateID(name); err == nil {
- return fmt.Errorf("Invalid repository name (%s), cannot specify 64-byte hexadecimal strings", name)
- }
- return nil
-}
diff --git a/reference/reference_test.go b/reference/reference_test.go
deleted file mode 100644
index 481a2dd97b..0000000000
--- a/reference/reference_test.go
+++ /dev/null
@@ -1,275 +0,0 @@
-package reference
-
-import (
- "testing"
-
- "github.com/opencontainers/go-digest"
-)
-
-func TestValidateReferenceName(t *testing.T) {
- validRepoNames := []string{
- "docker/docker",
- "library/debian",
- "debian",
- "docker.io/docker/docker",
- "docker.io/library/debian",
- "docker.io/debian",
- "index.docker.io/docker/docker",
- "index.docker.io/library/debian",
- "index.docker.io/debian",
- "127.0.0.1:5000/docker/docker",
- "127.0.0.1:5000/library/debian",
- "127.0.0.1:5000/debian",
- "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
- }
- invalidRepoNames := []string{
- "https://github.com/docker/docker",
- "docker/Docker",
- "-docker",
- "-docker/docker",
- "-docker.io/docker/docker",
- "docker///docker",
- "docker.io/docker/Docker",
- "docker.io/docker///docker",
- "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
- "docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
- }
-
- for _, name := range invalidRepoNames {
- _, err := ParseNamed(name)
- if err == nil {
- t.Fatalf("Expected invalid repo name for %q", name)
- }
- }
-
- for _, name := range validRepoNames {
- _, err := ParseNamed(name)
- if err != nil {
- t.Fatalf("Error parsing repo name %s, got: %q", name, err)
- }
- }
-}
-
-func TestValidateRemoteName(t *testing.T) {
- validRepositoryNames := []string{
- // Sanity check.
- "docker/docker",
-
- // Allow 64-character non-hexadecimal names (hexadecimal names are forbidden).
- "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
-
- // Allow embedded hyphens.
- "docker-rules/docker",
-
- // Allow multiple hyphens as well.
- "docker---rules/docker",
-
- //Username doc and image name docker being tested.
- "doc/docker",
-
- // single character names are now allowed.
- "d/docker",
- "jess/t",
-
- // Consecutive underscores.
- "dock__er/docker",
- }
- for _, repositoryName := range validRepositoryNames {
- _, err := ParseNamed(repositoryName)
- if err != nil {
- t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err)
- }
- }
-
- invalidRepositoryNames := []string{
- // Disallow capital letters.
- "docker/Docker",
-
- // Only allow one slash.
- "docker///docker",
-
- // Disallow 64-character hexadecimal.
- "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
-
- // Disallow leading and trailing hyphens in namespace.
- "-docker/docker",
- "docker-/docker",
- "-docker-/docker",
-
- // Don't allow underscores everywhere (as opposed to hyphens).
- "____/____",
-
- "_docker/_docker",
-
- // Disallow consecutive periods.
- "dock..er/docker",
- "dock_.er/docker",
- "dock-.er/docker",
-
- // No repository.
- "docker/",
-
- //namespace too long
- "this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker",
- }
- for _, repositoryName := range invalidRepositoryNames {
- if _, err := ParseNamed(repositoryName); err == nil {
- t.Errorf("Repository name should be invalid: %v", repositoryName)
- }
- }
-}
-
-func TestParseRepositoryInfo(t *testing.T) {
- type tcase struct {
- RemoteName, NormalizedName, FullName, AmbiguousName, Hostname string
- }
-
- tcases := []tcase{
- {
- RemoteName: "fooo/bar",
- NormalizedName: "fooo/bar",
- FullName: "docker.io/fooo/bar",
- AmbiguousName: "index.docker.io/fooo/bar",
- Hostname: "docker.io",
- },
- {
- RemoteName: "library/ubuntu",
- NormalizedName: "ubuntu",
- FullName: "docker.io/library/ubuntu",
- AmbiguousName: "library/ubuntu",
- Hostname: "docker.io",
- },
- {
- RemoteName: "nonlibrary/ubuntu",
- NormalizedName: "nonlibrary/ubuntu",
- FullName: "docker.io/nonlibrary/ubuntu",
- AmbiguousName: "",
- Hostname: "docker.io",
- },
- {
- RemoteName: "other/library",
- NormalizedName: "other/library",
- FullName: "docker.io/other/library",
- AmbiguousName: "",
- Hostname: "docker.io",
- },
- {
- RemoteName: "private/moonbase",
- NormalizedName: "127.0.0.1:8000/private/moonbase",
- FullName: "127.0.0.1:8000/private/moonbase",
- AmbiguousName: "",
- Hostname: "127.0.0.1:8000",
- },
- {
- RemoteName: "privatebase",
- NormalizedName: "127.0.0.1:8000/privatebase",
- FullName: "127.0.0.1:8000/privatebase",
- AmbiguousName: "",
- Hostname: "127.0.0.1:8000",
- },
- {
- RemoteName: "private/moonbase",
- NormalizedName: "example.com/private/moonbase",
- FullName: "example.com/private/moonbase",
- AmbiguousName: "",
- Hostname: "example.com",
- },
- {
- RemoteName: "privatebase",
- NormalizedName: "example.com/privatebase",
- FullName: "example.com/privatebase",
- AmbiguousName: "",
- Hostname: "example.com",
- },
- {
- RemoteName: "private/moonbase",
- NormalizedName: "example.com:8000/private/moonbase",
- FullName: "example.com:8000/private/moonbase",
- AmbiguousName: "",
- Hostname: "example.com:8000",
- },
- {
- RemoteName: "privatebasee",
- NormalizedName: "example.com:8000/privatebasee",
- FullName: "example.com:8000/privatebasee",
- AmbiguousName: "",
- Hostname: "example.com:8000",
- },
- {
- RemoteName: "library/ubuntu-12.04-base",
- NormalizedName: "ubuntu-12.04-base",
- FullName: "docker.io/library/ubuntu-12.04-base",
- AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
- Hostname: "docker.io",
- },
- }
-
- for _, tcase := range tcases {
- refStrings := []string{tcase.NormalizedName, tcase.FullName}
- if tcase.AmbiguousName != "" {
- refStrings = append(refStrings, tcase.AmbiguousName)
- }
-
- var refs []Named
- for _, r := range refStrings {
- named, err := ParseNamed(r)
- if err != nil {
- t.Fatal(err)
- }
- refs = append(refs, named)
- named, err = WithName(r)
- if err != nil {
- t.Fatal(err)
- }
- refs = append(refs, named)
- }
-
- for _, r := range refs {
- if expected, actual := tcase.NormalizedName, r.Name(); expected != actual {
- t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual)
- }
- if expected, actual := tcase.FullName, r.FullName(); expected != actual {
- t.Fatalf("Invalid fullName for %q. Expected %q, got %q", r, expected, actual)
- }
- if expected, actual := tcase.Hostname, r.Hostname(); expected != actual {
- t.Fatalf("Invalid hostname for %q. Expected %q, got %q", r, expected, actual)
- }
- if expected, actual := tcase.RemoteName, r.RemoteName(); expected != actual {
- t.Fatalf("Invalid remoteName for %q. Expected %q, got %q", r, expected, actual)
- }
-
- }
- }
-}
-
-func TestParseReferenceWithTagAndDigest(t *testing.T) {
- ref, err := ParseNamed("busybox:latest@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")
- if err != nil {
- t.Fatal(err)
- }
- if _, isTagged := ref.(NamedTagged); isTagged {
- t.Fatalf("Reference from %q should not support tag", ref)
- }
- if _, isCanonical := ref.(Canonical); !isCanonical {
- t.Fatalf("Reference from %q should not support digest", ref)
- }
- if expected, actual := "busybox@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", ref.String(); actual != expected {
- t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual)
- }
-}
-
-func TestInvalidReferenceComponents(t *testing.T) {
- if _, err := WithName("-foo"); err == nil {
- t.Fatal("Expected WithName to detect invalid name")
- }
- ref, err := WithName("busybox")
- if err != nil {
- t.Fatal(err)
- }
- if _, err := WithTag(ref, "-foo"); err == nil {
- t.Fatal("Expected WithName to detect invalid tag")
- }
- if _, err := WithDigest(ref, digest.Digest("foo")); err == nil {
- t.Fatal("Expected WithName to detect invalid digest")
- }
-}
diff --git a/reference/store.go b/reference/store.go
index 35ae33660a..844ebf5319 100644
--- a/reference/store.go
+++ b/reference/store.go
@@ -9,6 +9,7 @@ import (
"sort"
"sync"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/pkg/ioutils"
"github.com/opencontainers/go-digest"
)
@@ -21,18 +22,18 @@ var (
// An Association is a tuple associating a reference with an image ID.
type Association struct {
- Ref Named
+ Ref reference.Named
ID digest.Digest
}
// Store provides the set of methods which can operate on a tag store.
type Store interface {
- References(id digest.Digest) []Named
- ReferencesByName(ref Named) []Association
- AddTag(ref Named, id digest.Digest, force bool) error
- AddDigest(ref Canonical, id digest.Digest, force bool) error
- Delete(ref Named) (bool, error)
- Get(ref Named) (digest.Digest, error)
+ References(id digest.Digest) []reference.Named
+ ReferencesByName(ref reference.Named) []Association
+ AddTag(ref reference.Named, id digest.Digest, force bool) error
+ AddDigest(ref reference.Canonical, id digest.Digest, force bool) error
+ Delete(ref reference.Named) (bool, error)
+ Get(ref reference.Named) (digest.Digest, error)
}
type store struct {
@@ -44,24 +45,28 @@ type store struct {
Repositories map[string]repository
// referencesByIDCache is a cache of references indexed by ID, to speed
// up References.
- referencesByIDCache map[digest.Digest]map[string]Named
+ referencesByIDCache map[digest.Digest]map[string]reference.Named
}
// Repository maps tags to digests. The key is a stringified Reference,
// including the repository name.
type repository map[string]digest.Digest
-type lexicalRefs []Named
+type lexicalRefs []reference.Named
-func (a lexicalRefs) Len() int { return len(a) }
-func (a lexicalRefs) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a lexicalRefs) Less(i, j int) bool { return a[i].String() < a[j].String() }
+func (a lexicalRefs) Len() int { return len(a) }
+func (a lexicalRefs) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a lexicalRefs) Less(i, j int) bool {
+ return a[i].String() < a[j].String()
+}
type lexicalAssociations []Association
-func (a lexicalAssociations) Len() int { return len(a) }
-func (a lexicalAssociations) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a lexicalAssociations) Less(i, j int) bool { return a[i].Ref.String() < a[j].Ref.String() }
+func (a lexicalAssociations) Len() int { return len(a) }
+func (a lexicalAssociations) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a lexicalAssociations) Less(i, j int) bool {
+ return a[i].Ref.String() < a[j].Ref.String()
+}
// NewReferenceStore creates a new reference store, tied to a file path where
// the set of references are serialized in JSON format.
@@ -74,7 +79,7 @@ func NewReferenceStore(jsonPath string) (Store, error) {
store := &store{
jsonPath: abspath,
Repositories: make(map[string]repository),
- referencesByIDCache: make(map[digest.Digest]map[string]Named),
+ referencesByIDCache: make(map[digest.Digest]map[string]reference.Named),
}
// Load the json file if it exists, otherwise create it.
if err := store.reload(); os.IsNotExist(err) {
@@ -89,43 +94,45 @@ func NewReferenceStore(jsonPath string) (Store, error) {
// AddTag adds a tag reference to the store. If force is set to true, existing
// references can be overwritten. This only works for tags, not digests.
-func (store *store) AddTag(ref Named, id digest.Digest, force bool) error {
- if _, isCanonical := ref.(Canonical); isCanonical {
+func (store *store) AddTag(ref reference.Named, id digest.Digest, force bool) error {
+ if _, isCanonical := ref.(reference.Canonical); isCanonical {
return errors.New("refusing to create a tag with a digest reference")
}
- return store.addReference(WithDefaultTag(ref), id, force)
+ return store.addReference(reference.TagNameOnly(ref), id, force)
}
// AddDigest adds a digest reference to the store.
-func (store *store) AddDigest(ref Canonical, id digest.Digest, force bool) error {
+func (store *store) AddDigest(ref reference.Canonical, id digest.Digest, force bool) error {
return store.addReference(ref, id, force)
}
-func (store *store) addReference(ref Named, id digest.Digest, force bool) error {
- if ref.Name() == string(digest.Canonical) {
+func (store *store) addReference(ref reference.Named, id digest.Digest, force bool) error {
+ refName := reference.FamiliarName(ref)
+ refStr := reference.FamiliarString(ref)
+
+ if refName == string(digest.Canonical) {
return errors.New("refusing to create an ambiguous tag using digest algorithm as name")
}
store.mu.Lock()
defer store.mu.Unlock()
- repository, exists := store.Repositories[ref.Name()]
+ repository, exists := store.Repositories[refName]
if !exists || repository == nil {
repository = make(map[string]digest.Digest)
- store.Repositories[ref.Name()] = repository
+ store.Repositories[refName] = repository
}
- refStr := ref.String()
oldID, exists := repository[refStr]
if exists {
// force only works for tags
- if digested, isDigest := ref.(Canonical); isDigest {
+ if digested, isDigest := ref.(reference.Canonical); isDigest {
return fmt.Errorf("Cannot overwrite digest %s", digested.Digest().String())
}
if !force {
- return fmt.Errorf("Conflict: Tag %s is already set to image %s, if you want to replace it, please use -f option", ref.String(), oldID.String())
+ return fmt.Errorf("Conflict: Tag %s is already set to image %s, if you want to replace it, please use -f option", refStr, oldID.String())
}
if store.referencesByIDCache[oldID] != nil {
@@ -138,7 +145,7 @@ func (store *store) addReference(ref Named, id digest.Digest, force bool) error
repository[refStr] = id
if store.referencesByIDCache[id] == nil {
- store.referencesByIDCache[id] = make(map[string]Named)
+ store.referencesByIDCache[id] = make(map[string]reference.Named)
}
store.referencesByIDCache[id][refStr] = ref
@@ -147,24 +154,24 @@ func (store *store) addReference(ref Named, id digest.Digest, force bool) error
// Delete deletes a reference from the store. It returns true if a deletion
// happened, or false otherwise.
-func (store *store) Delete(ref Named) (bool, error) {
- ref = WithDefaultTag(ref)
+func (store *store) Delete(ref reference.Named) (bool, error) {
+ ref = reference.TagNameOnly(ref)
+
+ refName := reference.FamiliarName(ref)
+ refStr := reference.FamiliarString(ref)
store.mu.Lock()
defer store.mu.Unlock()
- repoName := ref.Name()
-
- repository, exists := store.Repositories[repoName]
+ repository, exists := store.Repositories[refName]
if !exists {
return false, ErrDoesNotExist
}
- refStr := ref.String()
if id, exists := repository[refStr]; exists {
delete(repository, refStr)
if len(repository) == 0 {
- delete(store.Repositories, repoName)
+ delete(store.Repositories, refName)
}
if store.referencesByIDCache[id] != nil {
delete(store.referencesByIDCache[id], refStr)
@@ -179,18 +186,34 @@ func (store *store) Delete(ref Named) (bool, error) {
}
// Get retrieves an item from the store by reference
-func (store *store) Get(ref Named) (digest.Digest, error) {
- ref = WithDefaultTag(ref)
+func (store *store) Get(ref reference.Named) (digest.Digest, error) {
+ if canonical, ok := ref.(reference.Canonical); ok {
+ // If reference contains both tag and digest, only
+ // lookup by digest as it takes precendent over
+ // tag, until tag/digest combos are stored.
+ if _, ok := ref.(reference.Tagged); ok {
+ var err error
+ ref, err = reference.WithDigest(reference.TrimNamed(canonical), canonical.Digest())
+ if err != nil {
+ return "", err
+ }
+ }
+ } else {
+ ref = reference.TagNameOnly(ref)
+ }
+
+ refName := reference.FamiliarName(ref)
+ refStr := reference.FamiliarString(ref)
store.mu.RLock()
defer store.mu.RUnlock()
- repository, exists := store.Repositories[ref.Name()]
+ repository, exists := store.Repositories[refName]
if !exists || repository == nil {
return "", ErrDoesNotExist
}
- id, exists := repository[ref.String()]
+ id, exists := repository[refStr]
if !exists {
return "", ErrDoesNotExist
}
@@ -200,7 +223,7 @@ func (store *store) Get(ref Named) (digest.Digest, error) {
// References returns a slice of references to the given ID. The slice
// will be nil if there are no references to this ID.
-func (store *store) References(id digest.Digest) []Named {
+func (store *store) References(id digest.Digest) []reference.Named {
store.mu.RLock()
defer store.mu.RUnlock()
@@ -208,7 +231,7 @@ func (store *store) References(id digest.Digest) []Named {
// 1) We must not return a mutable
// 2) It would be ugly to expose the extraneous map keys to callers.
- var references []Named
+ var references []reference.Named
for _, ref := range store.referencesByIDCache[id] {
references = append(references, ref)
}
@@ -221,18 +244,20 @@ func (store *store) References(id digest.Digest) []Named {
// ReferencesByName returns the references for a given repository name.
// If there are no references known for this repository name,
// ReferencesByName returns nil.
-func (store *store) ReferencesByName(ref Named) []Association {
+func (store *store) ReferencesByName(ref reference.Named) []Association {
+ refName := reference.FamiliarName(ref)
+
store.mu.RLock()
defer store.mu.RUnlock()
- repository, exists := store.Repositories[ref.Name()]
+ repository, exists := store.Repositories[refName]
if !exists {
return nil
}
var associations []Association
for refStr, refID := range repository {
- ref, err := ParseNamed(refStr)
+ ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
// Should never happen
return nil
@@ -270,13 +295,13 @@ func (store *store) reload() error {
for _, repository := range store.Repositories {
for refStr, refID := range repository {
- ref, err := ParseNamed(refStr)
+ ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
// Should never happen
continue
}
if store.referencesByIDCache[refID] == nil {
- store.referencesByIDCache[refID] = make(map[string]Named)
+ store.referencesByIDCache[refID] = make(map[string]reference.Named)
}
store.referencesByIDCache[refID][refStr] = ref
}
diff --git a/reference/store_test.go b/reference/store_test.go
index 0d96e6b694..8f0ff6304e 100644
--- a/reference/store_test.go
+++ b/reference/store_test.go
@@ -8,6 +8,7 @@ import (
"strings"
"testing"
+ "github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest"
)
@@ -45,7 +46,7 @@ func TestLoad(t *testing.T) {
}
for refStr, expectedID := range saveLoadTestCases {
- ref, err := ParseNamed(refStr)
+ ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
t.Fatalf("failed to parse reference: %v", err)
}
@@ -74,11 +75,11 @@ func TestSave(t *testing.T) {
}
for refStr, id := range saveLoadTestCases {
- ref, err := ParseNamed(refStr)
+ ref, err := reference.ParseNormalizedNamed(refStr)
if err != nil {
t.Fatalf("failed to parse reference: %v", err)
}
- if canonical, ok := ref.(Canonical); ok {
+ if canonical, ok := ref.(reference.Canonical); ok {
err = store.AddDigest(canonical, id, false)
if err != nil {
t.Fatalf("could not add digest reference %s: %v", refStr, err)
@@ -120,7 +121,7 @@ func TestAddDeleteGet(t *testing.T) {
testImageID3 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e")
// Try adding a reference with no tag or digest
- nameOnly, err := WithName("username/repo")
+ nameOnly, err := reference.ParseNormalizedNamed("username/repo")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -129,7 +130,7 @@ func TestAddDeleteGet(t *testing.T) {
}
// Add a few references
- ref1, err := ParseNamed("username/repo1:latest")
+ ref1, err := reference.ParseNormalizedNamed("username/repo1:latest")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -137,7 +138,7 @@ func TestAddDeleteGet(t *testing.T) {
t.Fatalf("error adding to store: %v", err)
}
- ref2, err := ParseNamed("username/repo1:old")
+ ref2, err := reference.ParseNormalizedNamed("username/repo1:old")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -145,7 +146,7 @@ func TestAddDeleteGet(t *testing.T) {
t.Fatalf("error adding to store: %v", err)
}
- ref3, err := ParseNamed("username/repo1:alias")
+ ref3, err := reference.ParseNormalizedNamed("username/repo1:alias")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -153,7 +154,7 @@ func TestAddDeleteGet(t *testing.T) {
t.Fatalf("error adding to store: %v", err)
}
- ref4, err := ParseNamed("username/repo2:latest")
+ ref4, err := reference.ParseNormalizedNamed("username/repo2:latest")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -161,11 +162,11 @@ func TestAddDeleteGet(t *testing.T) {
t.Fatalf("error adding to store: %v", err)
}
- ref5, err := ParseNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c")
+ ref5, err := reference.ParseNormalizedNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
- if err = store.AddDigest(ref5.(Canonical), testImageID2, false); err != nil {
+ if err = store.AddDigest(ref5.(reference.Canonical), testImageID2, false); err != nil {
t.Fatalf("error adding to store: %v", err)
}
@@ -228,7 +229,7 @@ func TestAddDeleteGet(t *testing.T) {
}
// Get should return ErrDoesNotExist for a nonexistent repo
- nonExistRepo, err := ParseNamed("username/nonexistrepo:latest")
+ nonExistRepo, err := reference.ParseNormalizedNamed("username/nonexistrepo:latest")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -237,7 +238,7 @@ func TestAddDeleteGet(t *testing.T) {
}
// Get should return ErrDoesNotExist for a nonexistent tag
- nonExistTag, err := ParseNamed("username/repo1:nonexist")
+ nonExistTag, err := reference.ParseNormalizedNamed("username/repo1:nonexist")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -263,7 +264,7 @@ func TestAddDeleteGet(t *testing.T) {
}
// Check ReferencesByName
- repoName, err := WithName("username/repo1")
+ repoName, err := reference.ParseNormalizedNamed("username/repo1")
if err != nil {
t.Fatalf("could not parse reference: %v", err)
}
@@ -334,7 +335,7 @@ func TestInvalidTags(t *testing.T) {
id := digest.Digest("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6")
// sha256 as repo name
- ref, err := ParseNamed("sha256:abc")
+ ref, err := reference.ParseNormalizedNamed("sha256:abc")
if err != nil {
t.Fatal(err)
}
@@ -344,7 +345,7 @@ func TestInvalidTags(t *testing.T) {
}
// setting digest as a tag
- ref, err = ParseNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6")
+ ref, err = reference.ParseNormalizedNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6")
if err != nil {
t.Fatal(err)
}
diff --git a/registry/config.go b/registry/config.go
index ce98e85c7e..ff72381dc5 100644
--- a/registry/config.go
+++ b/registry/config.go
@@ -10,7 +10,6 @@ import (
"github.com/docker/distribution/reference"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/opts"
- forkedref "github.com/docker/docker/reference"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)
@@ -271,8 +270,9 @@ func ValidateMirror(val string) (string, error) {
// ValidateIndexName validates an index name.
func ValidateIndexName(val string) (string, error) {
- if val == forkedref.LegacyDefaultHostname {
- val = forkedref.DefaultHostname
+ // TODO: upstream this to check to reference package
+ if val == "index.docker.io" {
+ val = "docker.io"
}
if strings.HasPrefix(val, "-") || strings.HasSuffix(val, "-") {
return "", fmt.Errorf("Invalid index name (%s). Cannot begin or end with a hyphen.", val)
@@ -328,13 +328,8 @@ func newRepositoryInfo(config *serviceConfig, name reference.Named) (*Repository
}
official := !strings.ContainsRune(reference.FamiliarName(name), '/')
- // TODO: remove used of forked reference package
- nameref, err := forkedref.ParseNamed(name.String())
- if err != nil {
- return nil, err
- }
return &RepositoryInfo{
- Named: nameref,
+ Name: reference.TrimNamed(name),
Index: index,
Official: official,
}, nil
diff --git a/registry/registry_mock_test.go b/registry/registry_mock_test.go
index 21fc1fdcc7..58b05d3849 100644
--- a/registry/registry_mock_test.go
+++ b/registry/registry_mock_test.go
@@ -17,8 +17,8 @@ import (
"testing"
"time"
+ "github.com/docker/distribution/reference"
registrytypes "github.com/docker/docker/api/types/registry"
- "github.com/docker/docker/reference"
"github.com/gorilla/mux"
"github.com/Sirupsen/logrus"
diff --git a/registry/registry_test.go b/registry/registry_test.go
index 7ab10721e0..1cbaaf4d46 100644
--- a/registry/registry_test.go
+++ b/registry/registry_test.go
@@ -14,7 +14,6 @@ import (
"github.com/docker/distribution/registry/client/transport"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
- forkedref "github.com/docker/docker/reference"
)
var (
@@ -202,7 +201,7 @@ func TestGetRemoteImageLayer(t *testing.T) {
func TestGetRemoteTag(t *testing.T) {
r := spawnTestRegistrySession(t)
- repoRef, err := forkedref.ParseNamed(REPO)
+ repoRef, err := reference.ParseNormalizedNamed(REPO)
if err != nil {
t.Fatal(err)
}
@@ -212,7 +211,7 @@ func TestGetRemoteTag(t *testing.T) {
}
assertEqual(t, tag, imageID, "Expected tag test to map to "+imageID)
- bazRef, err := forkedref.ParseNamed("foo42/baz")
+ bazRef, err := reference.ParseNormalizedNamed("foo42/baz")
if err != nil {
t.Fatal(err)
}
@@ -224,7 +223,7 @@ func TestGetRemoteTag(t *testing.T) {
func TestGetRemoteTags(t *testing.T) {
r := spawnTestRegistrySession(t)
- repoRef, err := forkedref.ParseNamed(REPO)
+ repoRef, err := reference.ParseNormalizedNamed(REPO)
if err != nil {
t.Fatal(err)
}
@@ -236,7 +235,7 @@ func TestGetRemoteTags(t *testing.T) {
assertEqual(t, tags["latest"], imageID, "Expected tag latest to map to "+imageID)
assertEqual(t, tags["test"], imageID, "Expected tag test to map to "+imageID)
- bazRef, err := forkedref.ParseNamed("foo42/baz")
+ bazRef, err := reference.ParseNormalizedNamed("foo42/baz")
if err != nil {
t.Fatal(err)
}
@@ -253,7 +252,7 @@ func TestGetRepositoryData(t *testing.T) {
t.Fatal(err)
}
host := "http://" + parsedURL.Host + "/v1/"
- repoRef, err := forkedref.ParseNamed(REPO)
+ repoRef, err := reference.ParseNormalizedNamed(REPO)
if err != nil {
t.Fatal(err)
}
@@ -516,9 +515,9 @@ func TestParseRepositoryInfo(t *testing.T) {
t.Error(err)
} else {
checkEqual(t, repoInfo.Index.Name, expectedRepoInfo.Index.Name, reposName)
- checkEqual(t, repoInfo.RemoteName(), expectedRepoInfo.RemoteName, reposName)
- checkEqual(t, repoInfo.Name(), expectedRepoInfo.LocalName, reposName)
- checkEqual(t, repoInfo.FullName(), expectedRepoInfo.CanonicalName, reposName)
+ checkEqual(t, reference.Path(repoInfo.Name), expectedRepoInfo.RemoteName, reposName)
+ checkEqual(t, reference.FamiliarName(repoInfo.Name), expectedRepoInfo.LocalName, reposName)
+ checkEqual(t, repoInfo.Name.Name(), expectedRepoInfo.CanonicalName, reposName)
checkEqual(t, repoInfo.Index.Official, expectedRepoInfo.Index.Official, reposName)
checkEqual(t, repoInfo.Official, expectedRepoInfo.Official, reposName)
}
@@ -689,7 +688,7 @@ func TestMirrorEndpointLookup(t *testing.T) {
func TestPushRegistryTag(t *testing.T) {
r := spawnTestRegistrySession(t)
- repoRef, err := forkedref.ParseNamed(REPO)
+ repoRef, err := reference.ParseNormalizedNamed(REPO)
if err != nil {
t.Fatal(err)
}
@@ -711,7 +710,7 @@ func TestPushImageJSONIndex(t *testing.T) {
Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2",
},
}
- repoRef, err := forkedref.ParseNamed(REPO)
+ repoRef, err := reference.ParseNormalizedNamed(REPO)
if err != nil {
t.Fatal(err)
}
diff --git a/registry/session.go b/registry/session.go
index ade111bb6c..c71e778037 100644
--- a/registry/session.go
+++ b/registry/session.go
@@ -19,6 +19,7 @@ import (
"strings"
"github.com/Sirupsen/logrus"
+ "github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
@@ -26,7 +27,6 @@ import (
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/tarsum"
- "github.com/docker/docker/reference"
)
var (
@@ -324,7 +324,7 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
// argument, and returns data from the first one that answers the query
// successfully.
func (r *Session) GetRemoteTag(registries []string, repositoryRef reference.Named, askedTag string) (string, error) {
- repository := repositoryRef.RemoteName()
+ repository := reference.Path(repositoryRef)
if strings.Count(repository, "/") == 0 {
// This will be removed once the registry supports auto-resolution on
@@ -362,7 +362,7 @@ func (r *Session) GetRemoteTag(registries []string, repositoryRef reference.Name
// the first one that answers the query successfully. It returns a map with
// tag names as the keys and image IDs as the values.
func (r *Session) GetRemoteTags(registries []string, repositoryRef reference.Named) (map[string]string, error) {
- repository := repositoryRef.RemoteName()
+ repository := reference.Path(repositoryRef)
if strings.Count(repository, "/") == 0 {
// This will be removed once the registry supports auto-resolution on
@@ -416,7 +416,7 @@ func buildEndpointsList(headers []string, indexEp string) ([]string, error) {
// GetRepositoryData returns lists of images and endpoints for the repository
func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, error) {
- repositoryTarget := fmt.Sprintf("%srepositories/%s/images", r.indexEndpoint.String(), name.RemoteName())
+ repositoryTarget := fmt.Sprintf("%srepositories/%s/images", r.indexEndpoint.String(), reference.Path(name))
logrus.Debugf("[registry] Calling GET %s", repositoryTarget)
@@ -450,7 +450,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
- return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to pull repository %s: %q", res.StatusCode, name.RemoteName(), errBody), res)
+ return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to pull repository %s: %q", res.StatusCode, reference.Path(name), errBody), res)
}
var endpoints []string
@@ -605,7 +605,7 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registry string) error {
// "jsonify" the string
revision = "\"" + revision + "\""
- path := fmt.Sprintf("repositories/%s/tags/%s", remote.RemoteName(), tag)
+ path := fmt.Sprintf("repositories/%s/tags/%s", reference.Path(remote), tag)
req, err := http.NewRequest("PUT", registry+path, strings.NewReader(revision))
if err != nil {
@@ -619,7 +619,7 @@ func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registr
}
res.Body.Close()
if res.StatusCode != 200 && res.StatusCode != 201 {
- return httputils.NewHTTPRequestError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, remote.RemoteName()), res)
+ return httputils.NewHTTPRequestError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, reference.Path(remote)), res)
}
return nil
}
@@ -645,7 +645,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
if validate {
suffix = "images"
}
- u := fmt.Sprintf("%srepositories/%s/%s", r.indexEndpoint.String(), remote.RemoteName(), suffix)
+ u := fmt.Sprintf("%srepositories/%s/%s", r.indexEndpoint.String(), reference.Path(remote), suffix)
logrus.Debugf("[registry] PUT %s", u)
logrus.Debugf("Image list pushed to index:\n%s", imgListJSON)
headers := map[string][]string{
@@ -683,7 +683,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
- return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push repository %s: %q", res.StatusCode, remote.RemoteName(), errBody), res)
+ return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push repository %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
}
tokens = res.Header["X-Docker-Token"]
logrus.Debugf("Auth token: %v", tokens)
@@ -701,7 +701,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
if err != nil {
logrus.Debugf("Error reading response body: %s", err)
}
- return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push checksums %s: %q", res.StatusCode, remote.RemoteName(), errBody), res)
+ return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Error: Status %d trying to push checksums %s: %q", res.StatusCode, reference.Path(remote), errBody), res)
}
}
diff --git a/registry/types.go b/registry/types.go
index 8dbcb961f1..0c3cbd6913 100644
--- a/registry/types.go
+++ b/registry/types.go
@@ -1,8 +1,8 @@
package registry
import (
+ "github.com/docker/distribution/reference"
registrytypes "github.com/docker/docker/api/types/registry"
- "github.com/docker/docker/reference"
)
// RepositoryData tracks the image list, list of endpoints for a repository
@@ -57,7 +57,7 @@ var apiVersions = map[APIVersion]string{
// RepositoryInfo describes a repository
type RepositoryInfo struct {
- reference.Named
+ Name reference.Named
// Index points to registry information
Index *registrytypes.IndexInfo
// Official indicates whether the repository is considered official.