Add platform filtering on children handler
Fixes pulling of multi-arch images by limiting the expansion of the index by filtering to the current default platform. Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
		@@ -23,6 +23,7 @@ import (
 | 
			
		||||
	"github.com/containerd/containerd/content"
 | 
			
		||||
	"github.com/containerd/containerd/errdefs"
 | 
			
		||||
	"github.com/containerd/containerd/images"
 | 
			
		||||
	"github.com/containerd/containerd/platforms"
 | 
			
		||||
	"github.com/containerd/containerd/plugin"
 | 
			
		||||
	"github.com/containerd/containerd/reference"
 | 
			
		||||
	"github.com/containerd/containerd/remotes"
 | 
			
		||||
@@ -226,7 +227,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
 | 
			
		||||
	} else {
 | 
			
		||||
		handler = images.Handlers(append(pullCtx.BaseHandlers,
 | 
			
		||||
			remotes.FetchHandler(store, fetcher),
 | 
			
		||||
			images.ChildrenHandler(store))...,
 | 
			
		||||
			images.ChildrenHandler(store, platforms.Default()))...,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -307,7 +308,7 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
 | 
			
		||||
	pushHandler := remotes.PushHandler(cs, pusher)
 | 
			
		||||
 | 
			
		||||
	handlers := append(pushCtx.BaseHandlers,
 | 
			
		||||
		images.ChildrenHandler(cs),
 | 
			
		||||
		images.ChildrenHandler(cs, platforms.Default()),
 | 
			
		||||
		filterHandler,
 | 
			
		||||
		pushHandler,
 | 
			
		||||
	)
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ var imagesListCommand = cli.Command{
 | 
			
		||||
		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
 | 
			
		||||
		fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORM\tLABELS\t")
 | 
			
		||||
		for _, image := range imageList {
 | 
			
		||||
			size, err := image.Size(ctx, cs)
 | 
			
		||||
			size, err := image.Size(ctx, cs, platforms.Default())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name)
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/containerd/containerd/content"
 | 
			
		||||
	"github.com/containerd/containerd/images"
 | 
			
		||||
	"github.com/containerd/containerd/platforms"
 | 
			
		||||
	ocispecs "github.com/opencontainers/image-spec/specs-go"
 | 
			
		||||
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
@@ -32,7 +33,7 @@ func (c *Client) exportToOCITar(ctx context.Context, desc ocispec.Descriptor, wr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handlers := images.Handlers(
 | 
			
		||||
		images.ChildrenHandler(cs),
 | 
			
		||||
		images.ChildrenHandler(cs, platforms.Default()),
 | 
			
		||||
		images.HandlerFunc(exportHandler),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								image.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								image.go
									
									
									
									
									
								
							@@ -50,7 +50,7 @@ func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
 | 
			
		||||
 | 
			
		||||
func (i *image) Size(ctx context.Context) (int64, error) {
 | 
			
		||||
	provider := i.client.ContentStore()
 | 
			
		||||
	return i.i.Size(ctx, provider)
 | 
			
		||||
	return i.i.Size(ctx, provider, platforms.Default())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/containerd/containerd/content"
 | 
			
		||||
	"github.com/containerd/containerd/log"
 | 
			
		||||
	"github.com/containerd/containerd/platforms"
 | 
			
		||||
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"golang.org/x/sync/errgroup"
 | 
			
		||||
@@ -127,7 +128,7 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor)
 | 
			
		||||
//
 | 
			
		||||
// One can also replace this with another implementation to allow descending of
 | 
			
		||||
// arbitrary types.
 | 
			
		||||
func ChildrenHandler(provider content.Provider) HandlerFunc {
 | 
			
		||||
func ChildrenHandler(provider content.Provider, platform string) HandlerFunc {
 | 
			
		||||
	return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 | 
			
		||||
		var descs []ocispec.Descriptor
 | 
			
		||||
		switch desc.MediaType {
 | 
			
		||||
@@ -157,7 +158,21 @@ func ChildrenHandler(provider content.Provider) HandlerFunc {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			descs = append(descs, index.Manifests...)
 | 
			
		||||
			if platform != "" {
 | 
			
		||||
				matcher, err := platforms.Parse(platform)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for _, d := range index.Manifests {
 | 
			
		||||
					if d.Platform == nil || matcher.Match(*d.Platform) {
 | 
			
		||||
						descs = append(descs, d)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				descs = append(descs, index.Manifests...)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
 | 
			
		||||
			MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
 | 
			
		||||
			ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip:
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ func (image *Image) RootFS(ctx context.Context, provider content.Provider, platf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Size returns the total size of an image's packed resources.
 | 
			
		||||
func (image *Image) Size(ctx context.Context, provider content.Provider) (int64, error) {
 | 
			
		||||
func (image *Image) Size(ctx context.Context, provider content.Provider, platform string) (int64, error) {
 | 
			
		||||
	var size int64
 | 
			
		||||
	return size, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 | 
			
		||||
		if desc.Size < 0 {
 | 
			
		||||
@@ -66,7 +66,7 @@ func (image *Image) Size(ctx context.Context, provider content.Provider) (int64,
 | 
			
		||||
		}
 | 
			
		||||
		size += desc.Size
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}), ChildrenHandler(provider)), image.Target)
 | 
			
		||||
	}), ChildrenHandler(provider, platform)), image.Target)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform string) (ocispec.Manifest, error) {
 | 
			
		||||
@@ -196,7 +196,7 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
 | 
			
		||||
				platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}))
 | 
			
		||||
		}
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}), ChildrenHandler(provider)), image)
 | 
			
		||||
	}), ChildrenHandler(provider, "")), image)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RootFS returns the unpacked diffids that make up and images rootfs.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user