فهرست منبع

imageService/PullImage: Move reference parse to api

Make `PullImage` accept `reference.Named` directly instead of
duplicating the parsing code for both graphdriver and containerd image
service implementations.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paweł Gronowski 1 سال پیش
والد
کامیت
ccb37fa567

+ 1 - 1
api/server/router/image/backend.go

@@ -37,7 +37,7 @@ type importExportBackend interface {
 }
 }
 
 
 type registryBackend interface {
 type registryBackend interface {
-	PullImage(ctx context.Context, image, tag string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
+	PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 }
 }
 
 

+ 26 - 1
api/server/router/image/image_routes.go

@@ -67,10 +67,35 @@ func (ir *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrit
 			}
 			}
 		}
 		}
 
 
+		// Special case: "pull -a" may send an image name with a
+		// trailing :. This is ugly, but let's not break API
+		// compatibility.
+		image := strings.TrimSuffix(img, ":")
+
+		ref, err := reference.ParseNormalizedNamed(image)
+		if err != nil {
+			return errdefs.InvalidParameter(err)
+		}
+
+		// TODO(thaJeztah) this could use a WithTagOrDigest() utility
+		if tag != "" {
+			// The "tag" could actually be a digest.
+			var dgst digest.Digest
+			dgst, err = digest.Parse(tag)
+			if err == nil {
+				ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
+			} else {
+				ref, err = reference.WithTag(ref, tag)
+			}
+			if err != nil {
+				return errdefs.InvalidParameter(err)
+			}
+		}
+
 		// For a pull it is not an error if no auth was given. Ignore invalid
 		// For a pull it is not an error if no auth was given. Ignore invalid
 		// AuthConfig to increase compatibility with the existing API.
 		// AuthConfig to increase compatibility with the existing API.
 		authConfig, _ := registry.DecodeAuthConfig(r.Header.Get(registry.AuthHeader))
 		authConfig, _ := registry.DecodeAuthConfig(r.Header.Get(registry.AuthHeader))
-		progressErr = ir.backend.PullImage(ctx, img, tag, platform, metaHeaders, authConfig, output)
+		progressErr = ir.backend.PullImage(ctx, ref, platform, metaHeaders, authConfig, output)
 	} else { // import
 	} else { // import
 		src := r.Form.Get("fromSrc")
 		src := r.Form.Get("fromSrc")
 
 

+ 1 - 1
daemon/cluster/executor/backend.go

@@ -76,7 +76,7 @@ type VolumeBackend interface {
 
 
 // ImageBackend is used by an executor to perform image operations
 // ImageBackend is used by an executor to perform image operations
 type ImageBackend interface {
 type ImageBackend interface {
-	PullImage(ctx context.Context, image, tag string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
+	PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	GetRepository(context.Context, reference.Named, *registry.AuthConfig) (distribution.Repository, error)
 	GetRepository(context.Context, reference.Named, *registry.AuthConfig) (distribution.Repository, error)
 	GetImage(ctx context.Context, refOrID string, options opts.GetImageOpts) (*image.Image, error)
 	GetImage(ctx context.Context, refOrID string, options opts.GetImageOpts) (*image.Image, error)
 }
 }

+ 4 - 1
daemon/cluster/executor/container/adapter.go

@@ -104,7 +104,10 @@ func (c *containerAdapter) pullImage(ctx context.Context) error {
 	go func() {
 	go func() {
 		// TODO LCOW Support: This will need revisiting as
 		// TODO LCOW Support: This will need revisiting as
 		// the stack is built up to include LCOW support for swarm.
 		// the stack is built up to include LCOW support for swarm.
-		err := c.imageBackend.PullImage(ctx, c.container.image(), "", nil, metaHeaders, authConfig, pw)
+
+		// Make sure the image has a tag, otherwise it will pull all tags.
+		ref := reference.TagNameOnly(named)
+		err := c.imageBackend.PullImage(ctx, ref, nil, metaHeaders, authConfig, pw)
 		pw.CloseWithError(err)
 		pw.CloseWithError(err)
 	}()
 	}()
 
 

+ 1 - 2
daemon/containerd/image_builder.go

@@ -117,7 +117,6 @@ func (i *ImageService) pullForBuilder(ctx context.Context, name string, authConf
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	taggedRef := reference.TagNameOnly(ref)
 
 
 	pullRegistryAuth := &registry.AuthConfig{}
 	pullRegistryAuth := &registry.AuthConfig{}
 	if len(authConfigs) > 0 {
 	if len(authConfigs) > 0 {
@@ -131,7 +130,7 @@ func (i *ImageService) pullForBuilder(ctx context.Context, name string, authConf
 		pullRegistryAuth = &resolvedConfig
 		pullRegistryAuth = &resolvedConfig
 	}
 	}
 
 
-	if err := i.PullImage(ctx, ref.Name(), taggedRef.(reference.NamedTagged).Tag(), platform, nil, pullRegistryAuth, output); err != nil {
+	if err := i.PullImage(ctx, reference.TagNameOnly(ref), platform, nil, pullRegistryAuth, output); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 

+ 8 - 23
daemon/containerd/image_pull.go

@@ -16,36 +16,15 @@ import (
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/streamformatter"
-	"github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 )
 )
 
 
-// PullImage initiates a pull operation. image is the repository name to pull, and
-// tagOrDigest may be either empty, or indicate a specific tag or digest to pull.
-func (i *ImageService) PullImage(ctx context.Context, image, tagOrDigest string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
+// PullImage initiates a pull operation. ref is the image to pull.
+func (i *ImageService) PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
 	var opts []containerd.RemoteOpt
 	var opts []containerd.RemoteOpt
 	if platform != nil {
 	if platform != nil {
 		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
 		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
 	}
 	}
-	ref, err := reference.ParseNormalizedNamed(image)
-	if err != nil {
-		return errdefs.InvalidParameter(err)
-	}
-
-	// TODO(thaJeztah) this could use a WithTagOrDigest() utility
-	if tagOrDigest != "" {
-		// The "tag" could actually be a digest.
-		var dgst digest.Digest
-		dgst, err = digest.Parse(tagOrDigest)
-		if err == nil {
-			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
-		} else {
-			ref, err = reference.WithTag(ref, tagOrDigest)
-		}
-		if err != nil {
-			return errdefs.InvalidParameter(err)
-		}
-	}
 
 
 	resolver, _ := i.newResolverFromAuthConfig(ctx, authConfig)
 	resolver, _ := i.newResolverFromAuthConfig(ctx, authConfig)
 	opts = append(opts, containerd.WithResolver(resolver))
 	opts = append(opts, containerd.WithResolver(resolver))
@@ -77,6 +56,12 @@ func (i *ImageService) PullImage(ctx context.Context, image, tagOrDigest string,
 	ah := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 	ah := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 		if images.IsManifestType(desc.MediaType) {
 		if images.IsManifestType(desc.MediaType) {
 			if !sentPullingFrom {
 			if !sentPullingFrom {
+				var tagOrDigest string
+				if tagged, ok := ref.(reference.Tagged); ok {
+					tagOrDigest = tagged.Tag()
+				} else {
+					tagOrDigest = ref.String()
+				}
 				progress.Message(out, tagOrDigest, "Pulling from "+reference.Path(ref))
 				progress.Message(out, tagOrDigest, "Pulling from "+reference.Path(ref))
 				sentPullingFrom = true
 				sentPullingFrom = true
 			}
 			}

+ 1 - 1
daemon/image_service.go

@@ -27,7 +27,7 @@ import (
 type ImageService interface {
 type ImageService interface {
 	// Images
 	// Images
 
 
-	PullImage(ctx context.Context, name, tag string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
+	PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error
 	CreateImage(ctx context.Context, config []byte, parent string, contentStoreDigest digest.Digest) (builder.Image, error)
 	CreateImage(ctx context.Context, config []byte, parent string, contentStoreDigest digest.Digest) (builder.Image, error)
 	ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
 	ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)

+ 3 - 28
daemon/images/image_pull.go

@@ -3,7 +3,6 @@ package images // import "github.com/docker/docker/daemon/images"
 import (
 import (
 	"context"
 	"context"
 	"io"
 	"io"
-	"strings"
 	"time"
 	"time"
 
 
 	"github.com/containerd/containerd/leases"
 	"github.com/containerd/containerd/leases"
@@ -17,40 +16,16 @@ import (
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/streamformatter"
-	"github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 )
 )
 
 
 // PullImage initiates a pull operation. image is the repository name to pull, and
 // PullImage initiates a pull operation. image is the repository name to pull, and
 // tag may be either empty, or indicate a specific tag to pull.
 // tag may be either empty, or indicate a specific tag to pull.
-func (i *ImageService) PullImage(ctx context.Context, image, tag string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
+func (i *ImageService) PullImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
 	start := time.Now()
 	start := time.Now()
-	// Special case: "pull -a" may send an image name with a
-	// trailing :. This is ugly, but let's not break API
-	// compatibility.
-	image = strings.TrimSuffix(image, ":")
 
 
-	ref, err := reference.ParseNormalizedNamed(image)
-	if err != nil {
-		return errdefs.InvalidParameter(err)
-	}
-
-	if tag != "" {
-		// The "tag" could actually be a digest.
-		var dgst digest.Digest
-		dgst, err = digest.Parse(tag)
-		if err == nil {
-			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
-		} else {
-			ref, err = reference.WithTag(ref, tag)
-		}
-		if err != nil {
-			return errdefs.InvalidParameter(err)
-		}
-	}
-
-	err = i.pullImageWithReference(ctx, ref, platform, metaHeaders, authConfig, outStream)
+	err := i.pullImageWithReference(ctx, ref, platform, metaHeaders, authConfig, outStream)
 	imageActions.WithValues("pull").UpdateSince(start)
 	imageActions.WithValues("pull").UpdateSince(start)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -70,7 +45,7 @@ func (i *ImageService) PullImage(ctx context.Context, image, tag string, platfor
 		if errdefs.IsNotFound(err) && img != nil {
 		if errdefs.IsNotFound(err) && img != nil {
 			po := streamformatter.NewJSONProgressOutput(outStream, false)
 			po := streamformatter.NewJSONProgressOutput(outStream, false)
 			progress.Messagef(po, "", `WARNING: %s`, err.Error())
 			progress.Messagef(po, "", `WARNING: %s`, err.Error())
-			log.G(ctx).WithError(err).WithField("image", image).Warn("ignoring platform mismatch on single-arch image")
+			log.G(ctx).WithError(err).WithField("image", reference.FamiliarName(ref)).Warn("ignoring platform mismatch on single-arch image")
 		} else if err != nil {
 		} else if err != nil {
 			return err
 			return err
 		}
 		}