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:
Derek McGowan 2017-09-20 14:23:26 -07:00
parent 9934acb271
commit eef47ffad3
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
6 changed files with 27 additions and 10 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/reference" "github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes"
@ -226,7 +227,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
} else { } else {
handler = images.Handlers(append(pullCtx.BaseHandlers, handler = images.Handlers(append(pullCtx.BaseHandlers,
remotes.FetchHandler(store, fetcher), 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) pushHandler := remotes.PushHandler(cs, pusher)
handlers := append(pushCtx.BaseHandlers, handlers := append(pushCtx.BaseHandlers,
images.ChildrenHandler(cs), images.ChildrenHandler(cs, platforms.Default()),
filterHandler, filterHandler,
pushHandler, pushHandler,
) )

View File

@ -58,7 +58,7 @@ var imagesListCommand = cli.Command{
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0) tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORM\tLABELS\t") fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORM\tLABELS\t")
for _, image := range imageList { for _, image := range imageList {
size, err := image.Size(ctx, cs) size, err := image.Size(ctx, cs, platforms.Default())
if err != nil { if err != nil {
log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name) log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name)
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
ocispecs "github.com/opencontainers/image-spec/specs-go" ocispecs "github.com/opencontainers/image-spec/specs-go"
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"
@ -32,7 +33,7 @@ func (c *Client) exportToOCITar(ctx context.Context, desc ocispec.Descriptor, wr
} }
handlers := images.Handlers( handlers := images.Handlers(
images.ChildrenHandler(cs), images.ChildrenHandler(cs, platforms.Default()),
images.HandlerFunc(exportHandler), images.HandlerFunc(exportHandler),
) )

View File

@ -50,7 +50,7 @@ func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
func (i *image) Size(ctx context.Context) (int64, error) { func (i *image) Size(ctx context.Context) (int64, error) {
provider := i.client.ContentStore() 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) { func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {

View File

@ -7,6 +7,7 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/platforms"
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"
"golang.org/x/sync/errgroup" "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 // One can also replace this with another implementation to allow descending of
// arbitrary types. // 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) { return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
var descs []ocispec.Descriptor var descs []ocispec.Descriptor
switch desc.MediaType { switch desc.MediaType {
@ -157,7 +158,21 @@ func ChildrenHandler(provider content.Provider) HandlerFunc {
return nil, err return nil, err
} }
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...) descs = append(descs, index.Manifests...)
}
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip, case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig, MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip: ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip:

View File

@ -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. // 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 var size int64
return size, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { return size, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if desc.Size < 0 { if desc.Size < 0 {
@ -66,7 +66,7 @@ func (image *Image) Size(ctx context.Context, provider content.Provider) (int64,
} }
size += desc.Size size += desc.Size
return nil, nil 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) { 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})) platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}))
} }
return nil, nil return nil, nil
}), ChildrenHandler(provider)), image) }), ChildrenHandler(provider, "")), image)
} }
// RootFS returns the unpacked diffids that make up and images rootfs. // RootFS returns the unpacked diffids that make up and images rootfs.