Add option to pull all metadata

Add flags to pull and fetch to grab all metadata.
Add fetch option to pull only metadata.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
Derek McGowan 2019-08-23 15:48:05 -07:00
parent aae2d0d754
commit a40c3830df
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
6 changed files with 43 additions and 34 deletions

View File

@ -333,9 +333,8 @@ type RemoteContext struct {
// MaxConcurrentDownloads is the max concurrent content downloads for each pull. // MaxConcurrentDownloads is the max concurrent content downloads for each pull.
MaxConcurrentDownloads int MaxConcurrentDownloads int
// AppendDistributionSourceLabel allows fetcher to add distribute source // AllMetadata downloads all manifests and known-configuration files
// label for each blob content, which doesn't work for legacy schema1. AllMetadata bool
AppendDistributionSourceLabel bool
} }
func defaultRemoteContext() *RemoteContext { func defaultRemoteContext() *RemoteContext {

View File

@ -195,11 +195,10 @@ func WithMaxConcurrentDownloads(max int) RemoteOpt {
} }
} }
// WithAppendDistributionSourceLabel allows fetcher to add distribute source // WithAllMetadata downloads all manifests and known-configuration files
// label for each blob content, which doesn't work for legacy schema1. func WithAllMetadata() RemoteOpt {
func WithAppendDistributionSourceLabel() RemoteOpt {
return func(_ *Client, c *RemoteContext) error { return func(_ *Client, c *RemoteContext) error {
c.AppendDistributionSourceLabel = true c.AllMetadata = true
return nil return nil
} }
} }

View File

@ -67,8 +67,12 @@ Most of this is experimental and there are few leaps to make this work.`,
Usage: "pull content from all platforms", Usage: "pull content from all platforms",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "all-manifests", Name: "all-metadata",
Usage: "Pull manifests from all platforms and layers for a specific platform", Usage: "Pull metadata for all platforms",
},
cli.BoolFlag{
Name: "metadata-only",
Usage: "Pull all metadata including manifests and configs",
}, },
), ),
Action: func(clicontext *cli.Context) error { Action: func(clicontext *cli.Context) error {
@ -84,6 +88,7 @@ Most of this is experimental and there are few leaps to make this work.`,
if err != nil { if err != nil {
return err return err
} }
_, err = Fetch(ctx, client, ref, config) _, err = Fetch(ctx, client, ref, config)
return err return err
}, },
@ -97,10 +102,12 @@ type FetchConfig struct {
ProgressOutput io.Writer ProgressOutput io.Writer
// Labels to set on the content // Labels to set on the content
Labels []string Labels []string
// PlatformMatcher matches platforms, supersedes Platforms
PlatformMatcher platforms.MatchComparer
// Platforms to fetch // Platforms to fetch
Platforms []string Platforms []string
// Whether or not download all manifests // Whether or not download all metadata
IsAllManifests bool AllMetadata bool
} }
// NewFetchConfig returns the default FetchConfig from cli flags // NewFetchConfig returns the default FetchConfig from cli flags
@ -124,7 +131,13 @@ func NewFetchConfig(ctx context.Context, clicontext *cli.Context) (*FetchConfig,
config.Platforms = p config.Platforms = p
} }
config.IsAllManifests = clicontext.Bool("all-manifests") if clicontext.Bool("metadata-only") {
config.AllMetadata = true
// Any with an empty set is None
config.PlatformMatcher = platforms.Any()
} else if clicontext.Bool("all-metadata") {
config.AllMetadata = true
}
return config, nil return config, nil
} }
@ -160,12 +173,16 @@ func Fetch(ctx context.Context, client *containerd.Client, ref string, config *F
containerd.WithSchema1Conversion, containerd.WithSchema1Conversion,
} }
if config.IsAllManifests { if config.AllMetadata {
opts = append(opts, containerd.WithAppendDistributionSourceLabel()) opts = append(opts, containerd.WithAllMetadata())
} }
for _, platform := range config.Platforms { if config.PlatformMatcher != nil {
opts = append(opts, containerd.WithPlatform(platform)) opts = append(opts, containerd.WithPlatformMatcher(config.PlatformMatcher))
} else {
for _, platform := range config.Platforms {
opts = append(opts, containerd.WithPlatform(platform))
}
} }
img, err := client.Fetch(pctx, ref, opts...) img, err := client.Fetch(pctx, ref, opts...)

View File

@ -51,11 +51,11 @@ command. As part of this process, we do the following:
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "pull content from all platforms", Usage: "pull content and metadata from all platforms",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "all-manifests", Name: "all-metadata",
Usage: "Pull manifests from all platforms and layers for a specific platform", Usage: "Pull metadata for all platforms",
}, },
), ),
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {

View File

@ -99,9 +99,7 @@ func TestImagePullWithDistSourceLabel(t *testing.T) {
pMatcher := platforms.Default() pMatcher := platforms.Default()
// pull content without unpack and add distribution source label // pull content without unpack and add distribution source label
image, err := client.Pull(ctx, imageName, image, err := client.Pull(ctx, imageName, WithPlatformMatcher(pMatcher))
WithPlatformMatcher(pMatcher),
WithAppendDistributionSourceLabel())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -183,7 +181,7 @@ func TestImageUsage(t *testing.T) {
imageName = imageName + "@" + image.Target().Digest.String() imageName = imageName + "@" + image.Target().Digest.String()
// Fetch single platforms, but all manifests pulled // Fetch single platforms, but all manifests pulled
if _, err := client.Fetch(ctx, imageName, WithPlatformMatcher(testPlatform)); err != nil { if _, err := client.Fetch(ctx, imageName, WithPlatformMatcher(testPlatform), WithAllMetadata()); err != nil {
t.Fatal(err) t.Fatal(err)
} }

18
pull.go
View File

@ -140,7 +140,7 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
childrenHandler := images.ChildrenHandler(store) childrenHandler := images.ChildrenHandler(store)
// Set any children labels for that content // Set any children labels for that content
childrenHandler = images.SetChildrenLabels(store, childrenHandler) childrenHandler = images.SetChildrenLabels(store, childrenHandler)
if rCtx.AppendDistributionSourceLabel { if rCtx.AllMetadata {
// Filter manifests by platforms but allow to handle manifest // Filter manifests by platforms but allow to handle manifest
// and configuration for not-target platforms // and configuration for not-target platforms
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher) childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
@ -164,22 +164,18 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
}, },
) )
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
if err != nil {
return images.Image{}, err
}
handlers := append(rCtx.BaseHandlers, handlers := append(rCtx.BaseHandlers,
remotes.FetchHandler(store, fetcher), remotes.FetchHandler(store, fetcher),
convertibleHandler, convertibleHandler,
childrenHandler, childrenHandler,
appendDistSrcLabelHandler,
) )
// append distribution source label to blob data
if rCtx.AppendDistributionSourceLabel {
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
if err != nil {
return images.Image{}, err
}
handlers = append(handlers, appendDistSrcLabelHandler)
}
handler = images.Handlers(handlers...) handler = images.Handlers(handlers...)
converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) { converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {