Merge pull request #8744 from cardyok/bugfix_remote_fetch_mediatype
This commit is contained in:
commit
e7276fe35a
@ -451,7 +451,12 @@ var (
|
|||||||
Usage: "Retrieve blobs from a remote",
|
Usage: "Retrieve blobs from a remote",
|
||||||
ArgsUsage: "[flags] <remote> [<digest>, ...]",
|
ArgsUsage: "[flags] <remote> [<digest>, ...]",
|
||||||
Description: `Fetch blobs by digests from a remote.`,
|
Description: `Fetch blobs by digests from a remote.`,
|
||||||
Flags: commands.RegistryFlags,
|
Flags: append(commands.RegistryFlags, []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "media-type",
|
||||||
|
Usage: "Specify target mediatype for request header",
|
||||||
|
},
|
||||||
|
}...),
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
ref = context.Args().First()
|
ref = context.Args().First()
|
||||||
@ -486,7 +491,7 @@ var (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rc, _, err := fetcherByDigest.FetchByDigest(ctx, dgst)
|
rc, _, err := fetcherByDigest.FetchByDigest(ctx, dgst, remotes.WithMediaType(context.String("media-type")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/remotes"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
@ -151,12 +152,18 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, ps ...string) (*request, int64, error) {
|
func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, mediatype string, ps ...string) (*request, int64, error) {
|
||||||
headReq := r.request(host, http.MethodHead, ps...)
|
headReq := r.request(host, http.MethodHead, ps...)
|
||||||
if err := headReq.addNamespace(r.refspec.Hostname()); err != nil {
|
if err := headReq.addNamespace(r.refspec.Hostname()); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mediatype == "" {
|
||||||
|
headReq.header.Set("Accept", "*/*")
|
||||||
|
} else {
|
||||||
|
headReq.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
headResp, err := headReq.doWithRetries(ctx, nil)
|
headResp, err := headReq.doWithRetries(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@ -175,9 +182,15 @@ func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, ps .
|
|||||||
return getReq, headResp.ContentLength, nil
|
return getReq, headResp.ContentLength, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) {
|
func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...remotes.FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error) {
|
||||||
var desc ocispec.Descriptor
|
var desc ocispec.Descriptor
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))
|
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))
|
||||||
|
var config remotes.FetchByDigestConfig
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(ctx, &config); err != nil {
|
||||||
|
return nil, desc, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hosts := r.filterHosts(HostCapabilityPull)
|
hosts := r.filterHosts(HostCapabilityPull)
|
||||||
if len(hosts) == 0 {
|
if len(hosts) == 0 {
|
||||||
@ -196,7 +209,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i
|
|||||||
)
|
)
|
||||||
|
|
||||||
for _, host := range r.hosts {
|
for _, host := range r.hosts {
|
||||||
getReq, sz, err = r.createGetReq(ctx, host, "blobs", dgst.String())
|
getReq, sz, err = r.createGetReq(ctx, host, config.Mediatype, "blobs", dgst.String())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -209,7 +222,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i
|
|||||||
if getReq == nil {
|
if getReq == nil {
|
||||||
// Fall back to the "manifests" endpoint
|
// Fall back to the "manifests" endpoint
|
||||||
for _, host := range r.hosts {
|
for _, host := range r.hosts {
|
||||||
getReq, sz, err = r.createGetReq(ctx, host, "manifests", dgst.String())
|
getReq, sz, err = r.createGetReq(ctx, host, config.Mediatype, "manifests", dgst.String())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -231,7 +244,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i
|
|||||||
}
|
}
|
||||||
|
|
||||||
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) {
|
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) {
|
||||||
return r.open(ctx, getReq, "", offset)
|
return r.open(ctx, getReq, config.Mediatype, offset)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, desc, err
|
return nil, desc, err
|
||||||
|
@ -65,7 +65,7 @@ type FetcherByDigest interface {
|
|||||||
// FetcherByDigest usually returns an incomplete descriptor.
|
// FetcherByDigest usually returns an incomplete descriptor.
|
||||||
// Typically, the media type is always set to "application/octet-stream",
|
// Typically, the media type is always set to "application/octet-stream",
|
||||||
// and the annotations are unset.
|
// and the annotations are unset.
|
||||||
FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error)
|
FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pusher pushes content
|
// Pusher pushes content
|
||||||
@ -92,3 +92,20 @@ type PusherFunc func(ctx context.Context, desc ocispec.Descriptor) (content.Writ
|
|||||||
func (fn PusherFunc) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {
|
func (fn PusherFunc) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {
|
||||||
return fn(ctx, desc)
|
return fn(ctx, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchByDigestConfig provides configuration for fetching content by digest
|
||||||
|
type FetchByDigestConfig struct {
|
||||||
|
//Mediatype specifies mediatype header to append for fetch request
|
||||||
|
Mediatype string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchByDigestOpts allows callers to set options for fetch object
|
||||||
|
type FetchByDigestOpts func(context.Context, *FetchByDigestConfig) error
|
||||||
|
|
||||||
|
// WithMediaType sets the media type header for fetch request
|
||||||
|
func WithMediaType(mediatype string) FetchByDigestOpts {
|
||||||
|
return func(ctx context.Context, cfg *FetchByDigestConfig) error {
|
||||||
|
cfg.Mediatype = mediatype
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user