From 31f577ea49ed317f9e2ec2b8598ee3d68b01307d Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Thu, 10 Dec 2015 11:01:34 -0800 Subject: [PATCH] Clean up reference type switches Signed-off-by: Tonis Tiigi Upstream-commit: eeb2d4c1adbe4e00f9fbcdc70f9ac31997968e1d Component: engine --- components/engine/api/client/build.go | 20 +++----------- components/engine/api/client/create.go | 26 +++++-------------- components/engine/api/client/import.go | 1 - components/engine/api/client/pull.go | 25 ++++++------------ components/engine/api/client/tag.go | 5 ++-- components/engine/api/client/trust.go | 4 ++- .../engine/api/server/router/local/image.go | 8 ++---- .../engine/daemon/daemonbuilder/builder.go | 10 +------ components/engine/daemon/image_delete.go | 12 +-------- components/engine/distribution/pull_v2.go | 7 ++--- components/engine/image/tarexport/save.go | 26 +++++++++---------- components/engine/reference/reference.go | 19 ++++++++++++++ components/engine/reference/store.go | 19 +++----------- 13 files changed, 63 insertions(+), 119 deletions(-) diff --git a/components/engine/api/client/build.go b/components/engine/api/client/build.go index 2d1d0f2214..5d7b9f5da3 100644 --- a/components/engine/api/client/build.go +++ b/components/engine/api/client/build.go @@ -522,21 +522,9 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(reference.Name if err != nil { return nil, nil, err } - - digested := false - switch ref.(type) { - case reference.NamedTagged: - case reference.Canonical: - digested = true - default: - ref, err = reference.WithTag(ref, reference.DefaultTag) - if err != nil { - return nil, nil, err - } - } - - if !digested && isTrusted() { - trustedRef, err := translator(ref.(reference.NamedTagged)) + ref = reference.WithDefaultTag(ref) + if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() { + trustedRef, err := translator(ref) if err != nil { return nil, nil, err } @@ -544,7 +532,7 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(reference.Name line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", trustedRef.String())) resolvedTags = append(resolvedTags, &resolvedTag{ digestRef: trustedRef, - tagRef: ref.(reference.NamedTagged), + tagRef: ref, }) } } diff --git a/components/engine/api/client/create.go b/components/engine/api/client/create.go index 60d1838e28..0336e86f33 100644 --- a/components/engine/api/client/create.go +++ b/components/engine/api/client/create.go @@ -25,14 +25,11 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error { } var tag string - switch x := ref.(type) { + switch x := reference.WithDefaultTag(ref).(type) { case reference.Canonical: tag = x.Digest().String() case reference.NamedTagged: tag = x.Tag() - default: - // pull only the image tagged 'latest' if no tag was specified - tag = reference.DefaultTag } // Resolve the Repository name from fqn to RepositoryInfo @@ -97,24 +94,13 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc if err != nil { return nil, err } - - isCanonical := false - switch ref.(type) { - case reference.NamedTagged: - case reference.Canonical: - isCanonical = true - default: - ref, err = reference.WithTag(ref, reference.DefaultTag) - if err != nil { - return nil, err - } - } + ref = reference.WithDefaultTag(ref) var trustedRef reference.Canonical - if isTrusted() && !isCanonical { + if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() { var err error - trustedRef, err = cli.trustedReference(ref.(reference.NamedTagged)) + trustedRef, err = cli.trustedReference(ref) if err != nil { return nil, err } @@ -132,8 +118,8 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil { return nil, err } - if trustedRef != nil && !isCanonical { - if err := cli.tagTrusted(trustedRef, ref.(reference.NamedTagged)); err != nil { + if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil { + if err := cli.tagTrusted(trustedRef, ref); err != nil { return nil, err } } diff --git a/components/engine/api/client/import.go b/components/engine/api/client/import.go index 7d0fdb870c..692566d72b 100644 --- a/components/engine/api/client/import.go +++ b/components/engine/api/client/import.go @@ -59,7 +59,6 @@ func (cli *DockerCli) CmdImport(args ...string) error { } defer file.Close() in = file - } options := types.ImageImportOptions{ diff --git a/components/engine/api/client/pull.go b/components/engine/api/client/pull.go index 43cbc9e253..361c341d06 100644 --- a/components/engine/api/client/pull.go +++ b/components/engine/api/client/pull.go @@ -13,8 +13,6 @@ import ( "github.com/docker/docker/registry" ) -var errTagCantBeUsed = errors.New("tag can't be used with --all-tags/-a") - // CmdPull pulls an image or a repository from the registry. // // Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST] @@ -31,28 +29,21 @@ func (cli *DockerCli) CmdPull(args ...string) error { if err != nil { return err } + if *allTags && !reference.IsNameOnly(distributionRef) { + return errors.New("tag can't be used with --all-tags/-a") + } + + if !*allTags && reference.IsNameOnly(distributionRef) { + distributionRef = reference.WithDefaultTag(distributionRef) + fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag) + } var tag string switch x := distributionRef.(type) { case reference.Canonical: - if *allTags { - return errTagCantBeUsed - } tag = x.Digest().String() case reference.NamedTagged: - if *allTags { - return errTagCantBeUsed - } tag = x.Tag() - default: - if !*allTags { - tag = reference.DefaultTag - distributionRef, err = reference.WithTag(distributionRef, tag) - if err != nil { - return err - } - fmt.Fprintf(cli.out, "Using default tag: %s\n", tag) - } } ref := registry.ParseReference(tag) diff --git a/components/engine/api/client/tag.go b/components/engine/api/client/tag.go index b169194b96..a1492666d0 100644 --- a/components/engine/api/client/tag.go +++ b/components/engine/api/client/tag.go @@ -28,9 +28,8 @@ func (cli *DockerCli) CmdTag(args ...string) error { return errors.New("refusing to create a tag with a digest reference") } - tag := "" - tagged, isTagged := ref.(reference.NamedTagged) - if isTagged { + var tag string + if tagged, isTagged := ref.(reference.NamedTagged); isTagged { tag = tagged.Tag() } diff --git a/components/engine/api/client/trust.go b/components/engine/api/client/trust.go index a609cc8c8d..252b9b1260 100644 --- a/components/engine/api/client/trust.go +++ b/components/engine/api/client/trust.go @@ -334,9 +334,11 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr return err } trustedRef, err := reference.WithDigest(repoInfo, r.digest) + if err != nil { + return err + } if err := cli.tagTrusted(trustedRef, tagged); err != nil { return err - } } } diff --git a/components/engine/api/server/router/local/image.go b/components/engine/api/server/router/local/image.go index 15273ac276..c66a8d8f8b 100644 --- a/components/engine/api/server/router/local/image.go +++ b/components/engine/api/server/router/local/image.go @@ -154,8 +154,7 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r return err } - switch newRef.(type) { - case reference.Canonical: + if _, isCanonical := newRef.(reference.Canonical); isCanonical { return errors.New("cannot import digest reference") } @@ -496,15 +495,12 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) { 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) - } - nameWithTag := ref.String() if _, exists := uniqNames[nameWithTag]; !exists { diff --git a/components/engine/daemon/daemonbuilder/builder.go b/components/engine/daemon/daemonbuilder/builder.go index 09bab93a4a..7de4ff2eab 100644 --- a/components/engine/daemon/daemonbuilder/builder.go +++ b/components/engine/daemon/daemonbuilder/builder.go @@ -41,15 +41,7 @@ func (d Docker) Pull(name string) (*image.Image, error) { if err != nil { return nil, err } - switch ref.(type) { - case reference.NamedTagged: - case reference.Canonical: - default: - ref, err = reference.WithTag(ref, "latest") - if err != nil { - return nil, err - } - } + ref = reference.WithDefaultTag(ref) pullRegistryAuth := &types.AuthConfig{} if len(d.AuthConfigs) > 0 { diff --git a/components/engine/daemon/image_delete.go b/components/engine/daemon/image_delete.go index 6d8b7b1bac..ab8217b5e1 100644 --- a/components/engine/daemon/image_delete.go +++ b/components/engine/daemon/image_delete.go @@ -149,17 +149,7 @@ 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) { - switch ref.(type) { - case reference.NamedTagged: - case reference.Canonical: - default: - var err error - ref, err = reference.WithTag(ref, reference.DefaultTag) - if err != nil { - return nil, err - } - } - + ref = reference.WithDefaultTag(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. diff --git a/components/engine/distribution/pull_v2.go b/components/engine/distribution/pull_v2.go index d00ddc6c90..8fe47e519f 100644 --- a/components/engine/distribution/pull_v2.go +++ b/components/engine/distribution/pull_v2.go @@ -54,10 +54,7 @@ func (p *v2Puller) Pull(ctx context.Context, ref reference.Named) (fallback bool func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named) (err error) { var refs []reference.Named - taggedName := ref - if _, isTagged := ref.(reference.NamedTagged); isTagged { - refs = []reference.Named{ref} - } else if _, isCanonical := ref.(reference.Canonical); isCanonical { + if !reference.IsNameOnly(ref) { refs = []reference.Named{ref} } else { manSvc, err := p.repo.Manifests(ctx) @@ -92,7 +89,7 @@ func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named) (e layersDownloaded = layersDownloaded || pulledNew } - writeStatus(taggedName.String(), p.config.ProgressOutput, layersDownloaded) + writeStatus(ref.String(), p.config.ProgressOutput, layersDownloaded) return nil } diff --git a/components/engine/image/tarexport/save.go b/components/engine/image/tarexport/save.go index c67009e16a..b7022ac5d8 100644 --- a/components/engine/image/tarexport/save.go +++ b/components/engine/image/tarexport/save.go @@ -81,21 +81,19 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor, addAssoc(imgID, nil) continue } - if _, ok := ref.(reference.Canonical); !ok { - if _, ok := ref.(reference.NamedTagged); !ok { - assocs := l.rs.ReferencesByName(ref) - for _, assoc := range assocs { - addAssoc(assoc.ImageID, assoc.Ref) - } - if len(assocs) == 0 { - imgID, err := l.is.Search(name) - if err != nil { - return nil, err - } - addAssoc(imgID, nil) - } - continue + if reference.IsNameOnly(ref) { + assocs := l.rs.ReferencesByName(ref) + for _, assoc := range assocs { + addAssoc(assoc.ImageID, assoc.Ref) } + if len(assocs) == 0 { + imgID, err := l.is.Search(name) + if err != nil { + return nil, err + } + addAssoc(imgID, nil) + } + continue } var imgID image.ID if imgID, err = l.rs.Get(ref); err != nil { diff --git a/components/engine/reference/reference.go b/components/engine/reference/reference.go index 8e887e3637..1e3482475f 100644 --- a/components/engine/reference/reference.go +++ b/components/engine/reference/reference.go @@ -132,6 +132,25 @@ 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 +} + // splitHostname splits a repository name to hostname and remotename string. // If no valid hostname is found, the default hostname is used. Repository name // needs to be already validated before. diff --git a/components/engine/reference/store.go b/components/engine/reference/store.go index 85608f7e87..91c5c2aed2 100644 --- a/components/engine/reference/store.go +++ b/components/engine/reference/store.go @@ -64,19 +64,6 @@ 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 defaultTagIfNameOnly(ref Named) Named { - switch ref.(type) { - case NamedTagged: - return ref - case Canonical: - return ref - default: - // Should never fail - ref, _ = WithTag(ref, DefaultTag) - return ref - } -} - // NewReferenceStore creates a new reference store, tied to a file path where // the set of references are serialized in JSON format. func NewReferenceStore(jsonPath string) (Store, error) { @@ -107,7 +94,7 @@ func (store *store) AddTag(ref Named, id image.ID, force bool) error { if _, isCanonical := ref.(Canonical); isCanonical { return errors.New("refusing to create a tag with a digest reference") } - return store.addReference(defaultTagIfNameOnly(ref), id, force) + return store.addReference(WithDefaultTag(ref), id, force) } // AddDigest adds a digest reference to the store. @@ -162,7 +149,7 @@ func (store *store) addReference(ref Named, id image.ID, 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 = defaultTagIfNameOnly(ref) + ref = WithDefaultTag(ref) store.mu.Lock() defer store.mu.Unlock() @@ -194,7 +181,7 @@ func (store *store) Delete(ref Named) (bool, error) { // Get retrieves an item from the store by func (store *store) Get(ref Named) (image.ID, error) { - ref = defaultTagIfNameOnly(ref) + ref = WithDefaultTag(ref) store.mu.RLock() defer store.mu.RUnlock()