Add a manifest filter limiting the number of matches
Adds a manifest filter for pulling which ensures only one manifest from a manifest list is pulled even when multiple matches. Removes unused filter platform list. Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
parent
0a3f87ec2e
commit
3d1082e06d
10
client.go
10
client.go
@ -338,7 +338,7 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
return c.fetch(ctx, fetchCtx, ref)
|
||||
return c.fetch(ctx, fetchCtx, ref, 0)
|
||||
}
|
||||
|
||||
// Pull downloads the provided content into containerd's content store
|
||||
@ -372,7 +372,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
img, err := c.fetch(ctx, pullCtx, ref)
|
||||
img, err := c.fetch(ctx, pullCtx, ref, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -388,7 +388,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string) (images.Image, error) {
|
||||
func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, limit int) (images.Image, error) {
|
||||
store := c.ContentStore()
|
||||
name, desc, err := rCtx.Resolver.Resolve(ctx, ref)
|
||||
if err != nil {
|
||||
@ -414,6 +414,10 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string) (im
|
||||
childrenHandler = images.SetChildrenLabels(store, childrenHandler)
|
||||
// Filter children by platforms
|
||||
childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
|
||||
// Sort and limit manifests if a finite number is needed
|
||||
if limit > 0 {
|
||||
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
|
||||
}
|
||||
|
||||
handler = images.Handlers(append(rCtx.BaseHandlers,
|
||||
remotes.FetchHandler(store, fetcher),
|
||||
|
@ -19,6 +19,7 @@ package images
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
@ -182,44 +183,6 @@ func SetChildrenLabels(manager content.Manager, f HandlerFunc) HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// FilterPlatformList is a handler wrapper which limits the descriptors returned
|
||||
// by a handler to the specified platforms.
|
||||
func FilterPlatformList(f HandlerFunc, platformList ...string) HandlerFunc {
|
||||
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
children, err := f(ctx, desc)
|
||||
if err != nil {
|
||||
return children, err
|
||||
}
|
||||
|
||||
if len(platformList) == 0 {
|
||||
return children, nil
|
||||
}
|
||||
|
||||
var m platforms.Matcher
|
||||
|
||||
if len(platformList) > 0 {
|
||||
ps := make([]ocispec.Platform, len(platformList))
|
||||
for i, platform := range platformList {
|
||||
p, err := platforms.Parse(platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ps[i] = p
|
||||
}
|
||||
m = platforms.Any(ps...)
|
||||
}
|
||||
|
||||
var descs []ocispec.Descriptor
|
||||
for _, d := range children {
|
||||
if d.Platform == nil || m.Match(*d.Platform) {
|
||||
descs = append(descs, d)
|
||||
}
|
||||
}
|
||||
|
||||
return descs, nil
|
||||
}
|
||||
}
|
||||
|
||||
// FilterPlatforms is a handler wrapper which limits the descriptors returned
|
||||
// based on matching the specified platform matcher.
|
||||
func FilterPlatforms(f HandlerFunc, m platforms.Matcher) HandlerFunc {
|
||||
@ -244,3 +207,37 @@ func FilterPlatforms(f HandlerFunc, m platforms.Matcher) HandlerFunc {
|
||||
return descs, nil
|
||||
}
|
||||
}
|
||||
|
||||
// LimitManifests is a handler wrapper which filters the manifest descriptors
|
||||
// returned using the provided platform.
|
||||
// The results will be ordered according to the comparison operator and
|
||||
// use the ordering in the manifests for equal matches.
|
||||
// A limit of 0 or less is considered no limit.
|
||||
func LimitManifests(f HandlerFunc, m platforms.MatchComparer, n int) HandlerFunc {
|
||||
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
children, err := f(ctx, desc)
|
||||
if err != nil {
|
||||
return children, err
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case ocispec.MediaTypeImageIndex, MediaTypeDockerSchema2ManifestList:
|
||||
sort.SliceStable(children, func(i, j int) bool {
|
||||
if children[i].Platform == nil {
|
||||
return false
|
||||
}
|
||||
if children[j].Platform == nil {
|
||||
return true
|
||||
}
|
||||
return m.Less(*children[i].Platform, *children[j].Platform)
|
||||
})
|
||||
|
||||
if n > 0 && len(children) > n {
|
||||
children = children[:n]
|
||||
}
|
||||
default:
|
||||
// only limit manifests from an index
|
||||
}
|
||||
return children, nil
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user