c8d/pull: Handle pull all tags

Use the distribution code to query the remote repository for tags and
pull them sequentially just like the non-c8d pull.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski 2023-09-20 14:28:01 +02:00
parent 095d2a29a3
commit d9b5445f39
No known key found for this signature in database
GPG key ID: B85EFCFE26DEF92A
3 changed files with 45 additions and 8 deletions

View file

@ -2,6 +2,7 @@ package containerd
import (
"context"
"fmt"
"io"
"github.com/containerd/containerd"
@ -12,7 +13,7 @@ import (
"github.com/containerd/log"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/registry"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/distribution"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/internal/compatcontext"
@ -21,8 +22,43 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// 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 {
// PullImage initiates a pull operation. baseRef is the image to pull.
// If reference is not tagged, all tags are pulled.
func (i *ImageService) PullImage(ctx context.Context, baseRef reference.Named, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registrytypes.AuthConfig, outStream io.Writer) error {
out := streamformatter.NewJSONProgressOutput(outStream, false)
if tagged, ok := baseRef.(reference.NamedTagged); ok {
return i.pullTag(ctx, tagged, platform, metaHeaders, authConfig, out)
}
tags, err := distribution.Tags(ctx, baseRef, &distribution.Config{
RegistryService: i.registryService,
MetaHeaders: metaHeaders,
AuthConfig: authConfig,
})
if err != nil {
return err
}
for _, tag := range tags {
ref, err := reference.WithTag(baseRef, tag)
if err != nil {
log.G(ctx).WithFields(log.Fields{
"tag": tag,
"baseRef": baseRef,
}).Warn("invalid tag, won't pull")
continue
}
if err := i.pullTag(ctx, ref, platform, metaHeaders, authConfig, out); err != nil {
return fmt.Errorf("error pulling %s: %w", ref, err)
}
}
return nil
}
func (i *ImageService) pullTag(ctx context.Context, ref reference.NamedTagged, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *registrytypes.AuthConfig, out progress.Output) error {
var opts []containerd.RemoteOpt
if platform != nil {
opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
@ -49,7 +85,6 @@ func (i *ImageService) PullImage(ctx context.Context, ref reference.Named, platf
})
opts = append(opts, containerd.WithImageHandler(h))
out := streamformatter.NewJSONProgressOutput(outStream, false)
pp := pullProgress{store: i.client.ContentStore(), showExists: true}
finishProgress := jobs.showProgress(ctx, out, pp)

View file

@ -31,7 +31,7 @@ func (i *ImageService) newResolverFromAuthConfig(ctx context.Context, authConfig
}), tracker
}
func hostsWrapper(hostsFn docker.RegistryHosts, optAuthConfig *registrytypes.AuthConfig, regService RegistryConfigProvider) docker.RegistryHosts {
func hostsWrapper(hostsFn docker.RegistryHosts, optAuthConfig *registrytypes.AuthConfig, regService registryResolver) docker.RegistryHosts {
var authorizer docker.Authorizer
if optAuthConfig != nil {
authorizer = authorizerFromAuthConfig(*optAuthConfig)

View file

@ -30,16 +30,18 @@ type ImageService struct {
containers container.Store
snapshotter string
registryHosts docker.RegistryHosts
registryService RegistryConfigProvider
registryService registryResolver
eventsService *daemonevents.Events
pruneRunning atomic.Bool
refCountMounter snapshotter.Mounter
idMapping idtools.IdentityMapping
}
type RegistryConfigProvider interface {
type registryResolver interface {
IsInsecureRegistry(host string) bool
ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error)
LookupPullEndpoints(hostname string) ([]registry.APIEndpoint, error)
LookupPushEndpoints(hostname string) ([]registry.APIEndpoint, error)
}
type ImageServiceConfig struct {
@ -47,7 +49,7 @@ type ImageServiceConfig struct {
Containers container.Store
Snapshotter string
RegistryHosts docker.RegistryHosts
Registry RegistryConfigProvider
Registry registryResolver
EventsService *daemonevents.Events
RefCountMounter snapshotter.Mounter
IDMapping idtools.IdentityMapping