Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[20.10 backport] distribution: Error when pulling OCI artifacts #44413

Merged
merged 1 commit into from Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 16 additions & 1 deletion distribution/errors.go
Expand Up @@ -87,6 +87,19 @@ func (e notFoundError) Cause() error {
return e.cause
}

// unsupportedMediaTypeError is an error issued when attempted
// to pull unsupported content.
type unsupportedMediaTypeError struct {
MediaType string
}

func (e unsupportedMediaTypeError) InvalidParameter() {}

// Error returns the error string for unsupportedMediaTypeError.
func (e unsupportedMediaTypeError) Error() string {
return "unsupported media type " + e.MediaType
}

// TranslatePullError is used to convert an error from a registry pull
// operation to an error representing the entire pull operation. Any error
// information which is not used by the returned error gets output to
Expand Down Expand Up @@ -150,6 +163,8 @@ func continueOnError(err error, mirrorEndpoint bool) bool {
// Failures from a mirror endpoint should result in fallback to the
// canonical repo.
return mirrorEndpoint
case unsupportedMediaTypeError:
return false
case error:
return !strings.Contains(err.Error(), strings.ToLower(syscall.ESRCH.Error()))
}
Expand Down Expand Up @@ -179,7 +194,7 @@ func retryOnError(err error) error {
return xfer.DoNotRetry{Err: v.Err}
}
return retryOnError(v.Err)
case *client.UnexpectedHTTPResponseError:
case *client.UnexpectedHTTPResponseError, unsupportedMediaTypeError:
return xfer.DoNotRetry{Err: err}
case error:
if err == distribution.ErrBlobUnknown {
Expand Down
22 changes: 22 additions & 0 deletions distribution/pull_v2.go
Expand Up @@ -619,13 +619,32 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unv
return imageID, manifestDigest, nil
}

func checkSupportedMediaType(mediaType string) error {
supportedMediaTypes := []string{
"application/vnd.oci.image.",
"application/vnd.docker.",
}

lowerMt := strings.ToLower(mediaType)
for _, mt := range supportedMediaTypes {
if strings.HasPrefix(lowerMt, mt) {
return nil
}
}
return unsupportedMediaTypeError{MediaType: mediaType}
}

func (p *v2Puller) pullSchema2Layers(ctx context.Context, target distribution.Descriptor, layers []distribution.Descriptor, platform *specs.Platform) (id digest.Digest, err error) {
if _, err := p.config.ImageStore.Get(ctx, target.Digest); err == nil {
// If the image already exists locally, no need to pull
// anything.
return target.Digest, nil
}

if err := checkSupportedMediaType(target.MediaType); err != nil {
return "", err
}

var descriptors []xfer.DownloadDescriptor

// Note that the order of this loop is in the direction of bottom-most
Expand All @@ -634,6 +653,9 @@ func (p *v2Puller) pullSchema2Layers(ctx context.Context, target distribution.De
if err := d.Digest.Validate(); err != nil {
return "", errors.Wrapf(err, "could not validate layer digest %q", d.Digest)
}
if err := checkSupportedMediaType(d.MediaType); err != nil {
return "", err
}
layerDescriptor := &v2LayerDescriptor{
digest: d.Digest,
repo: p.repo,
Expand Down