Merge pull request #4040 from thaJeztah/move_api_errors

This commit is contained in:
Milos Gajdos 2023-09-15 09:36:36 +01:00 committed by GitHub
commit 612ad42609
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 367 additions and 289 deletions

View file

@ -10,21 +10,21 @@ import (
// TestErrorsManagement does a quick check of the Errors type to ensure that // TestErrorsManagement does a quick check of the Errors type to ensure that
// members are properly pushed and marshaled. // members are properly pushed and marshaled.
var ErrorCodeTest1 = Register("test.errors", ErrorDescriptor{ var ErrorCodeTest1 = register("test.errors", ErrorDescriptor{
Value: "TEST1", Value: "TEST1",
Message: "test error 1", Message: "test error 1",
Description: `Just a test message #1.`, Description: `Just a test message #1.`,
HTTPStatusCode: http.StatusInternalServerError, HTTPStatusCode: http.StatusInternalServerError,
}) })
var ErrorCodeTest2 = Register("test.errors", ErrorDescriptor{ var ErrorCodeTest2 = register("test.errors", ErrorDescriptor{
Value: "TEST2", Value: "TEST2",
Message: "test error 2", Message: "test error 2",
Description: `Just a test message #2.`, Description: `Just a test message #2.`,
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}) })
var ErrorCodeTest3 = Register("test.errors", ErrorDescriptor{ var ErrorCodeTest3 = register("test.errors", ErrorDescriptor{
Value: "TEST3", Value: "TEST3",
Message: "Sorry %q isn't valid", Message: "Sorry %q isn't valid",
Description: `Just a test message #3.`, Description: `Just a test message #3.`,

View file

@ -16,7 +16,7 @@ var (
var ( var (
// ErrorCodeUnknown is a generic error that can be used as a last // ErrorCodeUnknown is a generic error that can be used as a last
// resort if there is no situation-specific error message that can be used // resort if there is no situation-specific error message that can be used
ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ ErrorCodeUnknown = register("errcode", ErrorDescriptor{
Value: "UNKNOWN", Value: "UNKNOWN",
Message: "unknown error", Message: "unknown error",
Description: `Generic error returned when the error does not have an Description: `Generic error returned when the error does not have an
@ -25,7 +25,7 @@ var (
}) })
// ErrorCodeUnsupported is returned when an operation is not supported. // ErrorCodeUnsupported is returned when an operation is not supported.
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ ErrorCodeUnsupported = register("errcode", ErrorDescriptor{
Value: "UNSUPPORTED", Value: "UNSUPPORTED",
Message: "The operation is unsupported.", Message: "The operation is unsupported.",
Description: `The operation was unsupported due to a missing Description: `The operation was unsupported due to a missing
@ -35,7 +35,7 @@ var (
// ErrorCodeUnauthorized is returned if a request requires // ErrorCodeUnauthorized is returned if a request requires
// authentication. // authentication.
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ ErrorCodeUnauthorized = register("errcode", ErrorDescriptor{
Value: "UNAUTHORIZED", Value: "UNAUTHORIZED",
Message: "authentication required", Message: "authentication required",
Description: `The access controller was unable to authenticate Description: `The access controller was unable to authenticate
@ -47,7 +47,7 @@ var (
// ErrorCodeDenied is returned if a client does not have sufficient // ErrorCodeDenied is returned if a client does not have sufficient
// permission to perform an action. // permission to perform an action.
ErrorCodeDenied = Register("errcode", ErrorDescriptor{ ErrorCodeDenied = register("errcode", ErrorDescriptor{
Value: "DENIED", Value: "DENIED",
Message: "requested access to the resource is denied", Message: "requested access to the resource is denied",
Description: `The access controller denied access for the Description: `The access controller denied access for the
@ -57,7 +57,7 @@ var (
// ErrorCodeUnavailable provides a common error to report unavailability // ErrorCodeUnavailable provides a common error to report unavailability
// of a service or endpoint. // of a service or endpoint.
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ ErrorCodeUnavailable = register("errcode", ErrorDescriptor{
Value: "UNAVAILABLE", Value: "UNAVAILABLE",
Message: "service unavailable", Message: "service unavailable",
Description: "Returned when a service is not available", Description: "Returned when a service is not available",
@ -66,7 +66,7 @@ var (
// ErrorCodeTooManyRequests is returned if a client attempts too many // ErrorCodeTooManyRequests is returned if a client attempts too many
// times to contact a service endpoint. // times to contact a service endpoint.
ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{ ErrorCodeTooManyRequests = register("errcode", ErrorDescriptor{
Value: "TOOMANYREQUESTS", Value: "TOOMANYREQUESTS",
Message: "too many requests", Message: "too many requests",
Description: `Returned when a client attempts to contact a Description: `Returned when a client attempts to contact a
@ -75,6 +75,157 @@ var (
}) })
) )
const errGroup = "registry.api.v2"
var (
// ErrorCodeDigestInvalid is returned when uploading a blob if the
// provided digest does not match the blob contents.
ErrorCodeDigestInvalid = register(errGroup, ErrorDescriptor{
Value: "DIGEST_INVALID",
Message: "provided digest did not match uploaded content",
Description: `When a blob is uploaded, the registry will check that
the content matches the digest provided by the client. The error may
include a detail structure with the key "digest", including the
invalid digest string. This error may also be returned when a manifest
includes an invalid layer digest.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
ErrorCodeSizeInvalid = register(errGroup, ErrorDescriptor{
Value: "SIZE_INVALID",
Message: "provided length did not match content length",
Description: `When a layer is uploaded, the provided size will be
checked against the uploaded content. If they do not match, this error
will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
// content range is invalid.
ErrorCodeRangeInvalid = register(errGroup, ErrorDescriptor{
Value: "RANGE_INVALID",
Message: "invalid content range",
Description: `When a layer is uploaded, the provided range is checked
against the uploaded chunk. This error is returned if the range is
out of order.`,
HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
})
// ErrorCodeNameInvalid is returned when the name in the manifest does not
// match the provided name.
ErrorCodeNameInvalid = register(errGroup, ErrorDescriptor{
Value: "NAME_INVALID",
Message: "invalid repository name",
Description: `Invalid repository name encountered either during
manifest validation or any API operation.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeTagInvalid is returned when the tag in the manifest does not
// match the provided tag.
ErrorCodeTagInvalid = register(errGroup, ErrorDescriptor{
Value: "TAG_INVALID",
Message: "manifest tag did not match URI",
Description: `During a manifest upload, if the tag in the manifest
does not match the uri tag, this error will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeNameUnknown when the repository name is not known.
ErrorCodeNameUnknown = register(errGroup, ErrorDescriptor{
Value: "NAME_UNKNOWN",
Message: "repository name not known to registry",
Description: `This is returned if the name used during an operation is
unknown to the registry.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeManifestUnknown returned when image manifest is unknown.
ErrorCodeManifestUnknown = register(errGroup, ErrorDescriptor{
Value: "MANIFEST_UNKNOWN",
Message: "manifest unknown",
Description: `This error is returned when the manifest, identified by
name and tag is unknown to the repository.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeManifestInvalid returned when an image manifest is invalid,
// typically during a PUT operation. This error encompasses all errors
// encountered during manifest validation that aren't signature errors.
ErrorCodeManifestInvalid = register(errGroup, ErrorDescriptor{
Value: "MANIFEST_INVALID",
Message: "manifest invalid",
Description: `During upload, manifests undergo several checks ensuring
validity. If those checks fail, this error may be returned, unless a
more specific error is included. The detail will contain information
the failed validation.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeManifestUnverified is returned when the manifest fails
// signature verification.
ErrorCodeManifestUnverified = register(errGroup, ErrorDescriptor{
Value: "MANIFEST_UNVERIFIED",
Message: "manifest failed signature verification",
Description: `During manifest upload, if the manifest fails signature
verification, this error will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
// unknown to the registry.
ErrorCodeManifestBlobUnknown = register(errGroup, ErrorDescriptor{
Value: "MANIFEST_BLOB_UNKNOWN",
Message: "blob unknown to registry",
Description: `This error may be returned when a manifest blob is
unknown to the registry.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeBlobUnknown is returned when a blob is unknown to the
// registry. This can happen when the manifest references a nonexistent
// layer or the result is not found by a blob fetch.
ErrorCodeBlobUnknown = register(errGroup, ErrorDescriptor{
Value: "BLOB_UNKNOWN",
Message: "blob unknown to registry",
Description: `This error may be returned when a blob is unknown to the
registry in a specified repository. This can be returned with a
standard get or if a manifest references an unknown layer during
upload.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
ErrorCodeBlobUploadUnknown = register(errGroup, ErrorDescriptor{
Value: "BLOB_UPLOAD_UNKNOWN",
Message: "blob upload unknown to registry",
Description: `If a blob upload has been cancelled or was never
started, this error code may be returned.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
ErrorCodeBlobUploadInvalid = register(errGroup, ErrorDescriptor{
Value: "BLOB_UPLOAD_INVALID",
Message: "blob upload invalid",
Description: `The blob upload encountered an error and can no
longer proceed.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
// not an integer, or `n` is negative.
ErrorCodePaginationNumberInvalid = register(errGroup, ErrorDescriptor{
Value: "PAGINATION_NUMBER_INVALID",
Message: "invalid number of results requested",
Description: `Returned when the "n" parameter (number of results
to return) is not an integer, "n" is negative or "n" is bigger than
the maximum allowed.`,
HTTPStatusCode: http.StatusBadRequest,
})
)
var ( var (
nextCode = 1000 nextCode = 1000
registerLock sync.Mutex registerLock sync.Mutex
@ -83,6 +234,12 @@ var (
// Register will make the passed-in error known to the environment and // Register will make the passed-in error known to the environment and
// return a new ErrorCode // return a new ErrorCode
func Register(group string, descriptor ErrorDescriptor) ErrorCode { func Register(group string, descriptor ErrorDescriptor) ErrorCode {
return register(group, descriptor)
}
// register will make the passed-in error known to the environment and
// return a new ErrorCode
func register(group string, descriptor ErrorDescriptor) ErrorCode {
registerLock.Lock() registerLock.Lock()
defer registerLock.Unlock() defer registerLock.Unlock()

View file

@ -143,7 +143,7 @@ var (
Format: errorsBody, Format: errorsBody,
}, },
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodePaginationNumberInvalid, errcode.ErrorCodePaginationNumberInvalid,
}, },
} }
@ -164,7 +164,7 @@ var (
Format: errorsBody, Format: errorsBody,
}, },
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameUnknown, errcode.ErrorCodeNameUnknown,
}, },
} }
@ -550,8 +550,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "The name or reference was invalid.", Description: "The name or reference was invalid.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeTagInvalid, errcode.ErrorCodeTagInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -609,11 +609,11 @@ var routeDescriptors = []RouteDescriptor{
Format: errorsBody, Format: errorsBody,
}, },
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeTagInvalid, errcode.ErrorCodeTagInvalid,
ErrorCodeManifestInvalid, errcode.ErrorCodeManifestInvalid,
ErrorCodeManifestUnverified, errcode.ErrorCodeManifestUnverified,
ErrorCodeBlobUnknown, errcode.ErrorCodeBlobUnknown,
}, },
}, },
unauthorizedResponseDescriptor, unauthorizedResponseDescriptor,
@ -625,7 +625,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.", Description: "One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUnknown, errcode.ErrorCodeBlobUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -678,8 +678,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "The specified `name` or `reference` were invalid and the delete was unable to proceed.", Description: "The specified `name` or `reference` were invalid and the delete was unable to proceed.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeTagInvalid, errcode.ErrorCodeTagInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -695,8 +695,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "The specified `name` or `reference` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest or tag was already deleted if this response is returned.", Description: "The specified `name` or `reference` are unknown to the registry and the delete was unable to proceed. Clients can assume the manifest or tag was already deleted if this response is returned.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameUnknown, errcode.ErrorCodeNameUnknown,
ErrorCodeManifestUnknown, errcode.ErrorCodeManifestUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -775,8 +775,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.", Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -791,8 +791,8 @@ var routeDescriptors = []RouteDescriptor{
Format: errorsBody, Format: errorsBody,
}, },
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameUnknown, errcode.ErrorCodeNameUnknown,
ErrorCodeBlobUnknown, errcode.ErrorCodeBlobUnknown,
}, },
}, },
unauthorizedResponseDescriptor, unauthorizedResponseDescriptor,
@ -847,8 +847,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.", Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `tag`.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -858,8 +858,8 @@ var routeDescriptors = []RouteDescriptor{
{ {
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameUnknown, errcode.ErrorCodeNameUnknown,
ErrorCodeBlobUnknown, errcode.ErrorCodeBlobUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -910,8 +910,8 @@ var routeDescriptors = []RouteDescriptor{
Name: "Invalid Name or Digest", Name: "Invalid Name or Digest",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
}, },
}, },
{ {
@ -922,8 +922,8 @@ var routeDescriptors = []RouteDescriptor{
Format: errorsBody, Format: errorsBody,
}, },
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameUnknown, errcode.ErrorCodeNameUnknown,
ErrorCodeBlobUnknown, errcode.ErrorCodeBlobUnknown,
}, },
}, },
{ {
@ -1010,8 +1010,8 @@ var routeDescriptors = []RouteDescriptor{
Name: "Invalid Name or Digest", Name: "Invalid Name or Digest",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
}, },
}, },
{ {
@ -1065,8 +1065,8 @@ var routeDescriptors = []RouteDescriptor{
Name: "Invalid Name or Digest", Name: "Invalid Name or Digest",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
}, },
}, },
unauthorizedResponseDescriptor, unauthorizedResponseDescriptor,
@ -1122,8 +1122,8 @@ var routeDescriptors = []RouteDescriptor{
Name: "Invalid Name or Digest", Name: "Invalid Name or Digest",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
}, },
}, },
{ {
@ -1187,9 +1187,9 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was an error processing the upload and it must be restarted.", Description: "There was an error processing the upload and it must be restarted.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeBlobUploadInvalid, errcode.ErrorCodeBlobUploadInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1200,7 +1200,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "The upload is unknown to the registry. The upload must be restarted.", Description: "The upload is unknown to the registry. The upload must be restarted.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUploadUnknown, errcode.ErrorCodeBlobUploadUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1262,9 +1262,9 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was an error processing the upload and it must be restarted.", Description: "There was an error processing the upload and it must be restarted.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeBlobUploadInvalid, errcode.ErrorCodeBlobUploadInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1275,7 +1275,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "The upload is unknown to the registry. The upload must be restarted.", Description: "The upload is unknown to the registry. The upload must be restarted.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUploadUnknown, errcode.ErrorCodeBlobUploadUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1344,9 +1344,9 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was an error processing the upload and it must be restarted.", Description: "There was an error processing the upload and it must be restarted.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeBlobUploadInvalid, errcode.ErrorCodeBlobUploadInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1357,7 +1357,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "The upload is unknown to the registry. The upload must be restarted.", Description: "The upload is unknown to the registry. The upload must be restarted.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUploadUnknown, errcode.ErrorCodeBlobUploadUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1438,9 +1438,9 @@ var routeDescriptors = []RouteDescriptor{
Description: "There was an error processing the upload and it must be restarted.", Description: "There was an error processing the upload and it must be restarted.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid, errcode.ErrorCodeDigestInvalid,
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeBlobUploadInvalid, errcode.ErrorCodeBlobUploadInvalid,
errcode.ErrorCodeUnsupported, errcode.ErrorCodeUnsupported,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
@ -1452,7 +1452,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "The upload is unknown to the registry. The upload must be restarted.", Description: "The upload is unknown to the registry. The upload must be restarted.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUploadUnknown, errcode.ErrorCodeBlobUploadUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1497,8 +1497,8 @@ var routeDescriptors = []RouteDescriptor{
Description: "An error was encountered processing the delete. The client may ignore this error.", Description: "An error was encountered processing the delete. The client may ignore this error.",
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeNameInvalid, errcode.ErrorCodeNameInvalid,
ErrorCodeBlobUploadInvalid, errcode.ErrorCodeBlobUploadInvalid,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",
@ -1509,7 +1509,7 @@ var routeDescriptors = []RouteDescriptor{
Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.", Description: "The upload is unknown to the registry. The client may ignore this error and assume the upload has been deleted.",
StatusCode: http.StatusNotFound, StatusCode: http.StatusNotFound,
ErrorCodes: []errcode.ErrorCode{ ErrorCodes: []errcode.ErrorCode{
ErrorCodeBlobUploadUnknown, errcode.ErrorCodeBlobUploadUnknown,
}, },
Body: BodyDescriptor{ Body: BodyDescriptor{
ContentType: "application/json", ContentType: "application/json",

View file

@ -1,158 +0,0 @@
package v2
import (
"net/http"
"github.com/distribution/distribution/v3/registry/api/errcode"
)
const errGroup = "registry.api.v2"
var (
// ErrorCodeDigestInvalid is returned when uploading a blob if the
// provided digest does not match the blob contents.
ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "DIGEST_INVALID",
Message: "provided digest did not match uploaded content",
Description: `When a blob is uploaded, the registry will check that
the content matches the digest provided by the client. The error may
include a detail structure with the key "digest", including the
invalid digest string. This error may also be returned when a manifest
includes an invalid layer digest.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
ErrorCodeSizeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "SIZE_INVALID",
Message: "provided length did not match content length",
Description: `When a layer is uploaded, the provided size will be
checked against the uploaded content. If they do not match, this error
will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
// content range is invalid.
ErrorCodeRangeInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "RANGE_INVALID",
Message: "invalid content range",
Description: `When a layer is uploaded, the provided range is checked
against the uploaded chunk. This error is returned if the range is
out of order.`,
HTTPStatusCode: http.StatusRequestedRangeNotSatisfiable,
})
// ErrorCodeNameInvalid is returned when the name in the manifest does not
// match the provided name.
ErrorCodeNameInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "NAME_INVALID",
Message: "invalid repository name",
Description: `Invalid repository name encountered either during
manifest validation or any API operation.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeTagInvalid is returned when the tag in the manifest does not
// match the provided tag.
ErrorCodeTagInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "TAG_INVALID",
Message: "manifest tag did not match URI",
Description: `During a manifest upload, if the tag in the manifest
does not match the uri tag, this error will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeNameUnknown when the repository name is not known.
ErrorCodeNameUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "NAME_UNKNOWN",
Message: "repository name not known to registry",
Description: `This is returned if the name used during an operation is
unknown to the registry.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeManifestUnknown returned when image manifest is unknown.
ErrorCodeManifestUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "MANIFEST_UNKNOWN",
Message: "manifest unknown",
Description: `This error is returned when the manifest, identified by
name and tag is unknown to the repository.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeManifestInvalid returned when an image manifest is invalid,
// typically during a PUT operation. This error encompasses all errors
// encountered during manifest validation that aren't signature errors.
ErrorCodeManifestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "MANIFEST_INVALID",
Message: "manifest invalid",
Description: `During upload, manifests undergo several checks ensuring
validity. If those checks fail, this error may be returned, unless a
more specific error is included. The detail will contain information
the failed validation.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeManifestUnverified is returned when the manifest fails
// signature verification.
ErrorCodeManifestUnverified = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "MANIFEST_UNVERIFIED",
Message: "manifest failed signature verification",
Description: `During manifest upload, if the manifest fails signature
verification, this error will be returned.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
// unknown to the registry.
ErrorCodeManifestBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "MANIFEST_BLOB_UNKNOWN",
Message: "blob unknown to registry",
Description: `This error may be returned when a manifest blob is
unknown to the registry.`,
HTTPStatusCode: http.StatusBadRequest,
})
// ErrorCodeBlobUnknown is returned when a blob is unknown to the
// registry. This can happen when the manifest references a nonexistent
// layer or the result is not found by a blob fetch.
ErrorCodeBlobUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "BLOB_UNKNOWN",
Message: "blob unknown to registry",
Description: `This error may be returned when a blob is unknown to the
registry in a specified repository. This can be returned with a
standard get or if a manifest references an unknown layer during
upload.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
ErrorCodeBlobUploadUnknown = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "BLOB_UPLOAD_UNKNOWN",
Message: "blob upload unknown to registry",
Description: `If a blob upload has been cancelled or was never
started, this error code may be returned.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
ErrorCodeBlobUploadInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "BLOB_UPLOAD_INVALID",
Message: "blob upload invalid",
Description: `The blob upload encountered an error and can no
longer proceed.`,
HTTPStatusCode: http.StatusNotFound,
})
// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
// not an integer, or `n` is negative.
ErrorCodePaginationNumberInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
Value: "PAGINATION_NUMBER_INVALID",
Message: "invalid number of results requested",
Description: `Returned when the "n" parameter (number of results
to return) is not an integer, "n" is negative or "n" is bigger than
the maximum allowed.`,
HTTPStatusCode: http.StatusBadRequest,
})
)

View file

@ -0,0 +1,86 @@
package v2
import "github.com/distribution/distribution/v3/registry/api/errcode"
var (
// ErrorCodeDigestInvalid is returned when uploading a blob if the
// provided digest does not match the blob contents.
//
// Deprecated: use [errcode.ErrorCodeDigestInvalid].
ErrorCodeDigestInvalid = errcode.ErrorCodeDigestInvalid
// ErrorCodeSizeInvalid is returned when uploading a blob if the provided
//
// Deprecated: use [errcode.ErrorCodeSizeInvalid].
ErrorCodeSizeInvalid = errcode.ErrorCodeSizeInvalid
// ErrorCodeRangeInvalid is returned when uploading a blob if the provided
// content range is invalid.
//
// Deprecated: use [errcode.ErrorCodeRangeInvalid].
ErrorCodeRangeInvalid = errcode.ErrorCodeRangeInvalid
// ErrorCodeNameInvalid is returned when the name in the manifest does not
// match the provided name.
//
// Deprecated: use [errcode.ErrorCodeNameInvalid].
ErrorCodeNameInvalid = errcode.ErrorCodeNameInvalid
// ErrorCodeTagInvalid is returned when the tag in the manifest does not
// match the provided tag.
//
// Deprecated: use [errcode.ErrorCodeTagInvalid].
ErrorCodeTagInvalid = errcode.ErrorCodeTagInvalid
// ErrorCodeNameUnknown when the repository name is not known.
//
// Deprecated: use [errcode.ErrorCodeNameUnknown].
ErrorCodeNameUnknown = errcode.ErrorCodeNameUnknown
// ErrorCodeManifestUnknown returned when image manifest is unknown.
//
// Deprecated: use [errcode.ErrorCodeManifestUnknown].
ErrorCodeManifestUnknown = errcode.ErrorCodeManifestUnknown
// ErrorCodeManifestInvalid returned when an image manifest is invalid,
// typically during a PUT operation. This error encompasses all errors
// encountered during manifest validation that aren't signature errors.
//
// Deprecated: use [errcode.ErrorCodeManifestInvalid].
ErrorCodeManifestInvalid = errcode.ErrorCodeManifestInvalid
// ErrorCodeManifestUnverified is returned when the manifest fails
// signature verification.
//
// Deprecated: use [errcode.ErrorCodeManifestUnverified].
ErrorCodeManifestUnverified = errcode.ErrorCodeManifestUnverified
// ErrorCodeManifestBlobUnknown is returned when a manifest blob is
// unknown to the registry.
//
// Deprecated: use [errcode.ErrorCodeManifestBlobUnknown].
ErrorCodeManifestBlobUnknown = errcode.ErrorCodeManifestBlobUnknown
// ErrorCodeBlobUnknown is returned when a blob is unknown to the
// registry. This can happen when the manifest references a nonexistent
// layer or the result is not found by a blob fetch.
//
// Deprecated: use [errcode.ErrorCodeBlobUnknown].
ErrorCodeBlobUnknown = errcode.ErrorCodeBlobUnknown
// ErrorCodeBlobUploadUnknown is returned when an upload is unknown.
//
// Deprecated: use [errcode.ErrorCodeBlobUploadUnknown].
ErrorCodeBlobUploadUnknown = errcode.ErrorCodeBlobUploadUnknown
// ErrorCodeBlobUploadInvalid is returned when an upload is invalid.
//
// Deprecated: use [errcode.ErrorCodeBlobUploadInvalid].
ErrorCodeBlobUploadInvalid = errcode.ErrorCodeBlobUploadInvalid
// ErrorCodePaginationNumberInvalid is returned when the `n` parameter is
// not an integer, or `n` is negative.
//
// Deprecated: use [errcode.ErrorCodePaginationNumberInvalid].
ErrorCodePaginationNumberInvalid = errcode.ErrorCodePaginationNumberInvalid
)

View file

@ -9,7 +9,6 @@ import (
"github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/distribution/distribution/v3/testutil" "github.com/distribution/distribution/v3/testutil"
) )
@ -175,8 +174,8 @@ func TestUploadReadFrom(t *testing.T) {
if !ok { if !ok {
t.Fatalf("Not an 'Error' type: %#v", uploadErr[0]) t.Fatalf("Not an 'Error' type: %#v", uploadErr[0])
} }
if v2Err.Code != v2.ErrorCodeBlobUploadInvalid { if v2Err.Code != errcode.ErrorCodeBlobUploadInvalid {
t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), v2.ErrorCodeBlobUploadInvalid) t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), errcode.ErrorCodeBlobUploadInvalid)
} }
if expected := "blob upload invalid"; v2Err.Message != expected { if expected := "blob upload invalid"; v2Err.Message != expected {
t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected) t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected)
@ -463,8 +462,8 @@ func TestUploadWrite(t *testing.T) {
if !ok { if !ok {
t.Fatalf("Not an 'Error' type: %#v", uploadErr[0]) t.Fatalf("Not an 'Error' type: %#v", uploadErr[0])
} }
if v2Err.Code != v2.ErrorCodeBlobUploadInvalid { if v2Err.Code != errcode.ErrorCodeBlobUploadInvalid {
t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), v2.ErrorCodeBlobUploadInvalid) t.Fatalf("Unexpected error code: %s, expected %d", v2Err.Code.String(), errcode.ErrorCodeBlobUploadInvalid)
} }
if expected := "blob upload invalid"; v2Err.Message != expected { if expected := "blob upload invalid"; v2Err.Message != expected {
t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected) t.Fatalf("Unexpected error message: %q, expected %q", v2Err.Message, expected)

View file

@ -21,7 +21,6 @@ import (
"github.com/distribution/distribution/v3/manifest" "github.com/distribution/distribution/v3/manifest"
"github.com/distribution/distribution/v3/manifest/ocischema" "github.com/distribution/distribution/v3/manifest/ocischema"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/distribution/distribution/v3/testutil" "github.com/distribution/distribution/v3/testutil"
"github.com/distribution/distribution/v3/uuid" "github.com/distribution/distribution/v3/uuid"
"github.com/distribution/reference" "github.com/distribution/reference"
@ -1440,7 +1439,7 @@ func TestObtainsErrorForMissingTag(t *testing.T) {
var m testutil.RequestResponseMap var m testutil.RequestResponseMap
var errors errcode.Errors var errors errcode.Errors
errors = append(errors, v2.ErrorCodeManifestUnknown.WithDetail("unknown manifest")) errors = append(errors, errcode.ErrorCodeManifestUnknown.WithDetail("unknown manifest"))
errBytes, err := json.Marshal(errors) errBytes, err := json.Marshal(errors)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -339,7 +339,7 @@ func TestCatalogAPI(t *testing.T) {
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest) checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid) checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
// ----------------------------------- // -----------------------------------
// Case No. 6: request n > maxentries but <= total catalog // Case No. 6: request n > maxentries but <= total catalog
@ -360,7 +360,7 @@ func TestCatalogAPI(t *testing.T) {
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest) checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid) checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
// ----------------------------------- // -----------------------------------
// Case No. 7: n = 0 // Case No. 7: n = 0
@ -409,7 +409,7 @@ func TestCatalogAPI(t *testing.T) {
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest) checkResponse(t, "issuing catalog api check", resp, http.StatusBadRequest)
checkBodyHasErrorCodes(t, "invalid number of results requested", resp, v2.ErrorCodePaginationNumberInvalid) checkBodyHasErrorCodes(t, "invalid number of results requested", resp, errcode.ErrorCodePaginationNumberInvalid)
// ----------------------------------- // -----------------------------------
// Case No. 9: n = 5, max = 5, total catalog = 4 // Case No. 9: n = 5, max = 5, total catalog = 4
@ -504,13 +504,13 @@ func TestTagsAPI(t *testing.T) {
name: "negative n query parameter", name: "negative n query parameter",
queryParams: url.Values{"n": []string{"-1"}}, queryParams: url.Values{"n": []string{"-1"}},
expectedStatusCode: http.StatusBadRequest, expectedStatusCode: http.StatusBadRequest,
expectedBodyErr: &v2.ErrorCodePaginationNumberInvalid, expectedBodyErr: &errcode.ErrorCodePaginationNumberInvalid,
}, },
{ {
name: "non integer n query parameter", name: "non integer n query parameter",
queryParams: url.Values{"n": []string{"foo"}}, queryParams: url.Values{"n": []string{"foo"}},
expectedStatusCode: http.StatusBadRequest, expectedStatusCode: http.StatusBadRequest,
expectedBodyErr: &v2.ErrorCodePaginationNumberInvalid, expectedBodyErr: &errcode.ErrorCodePaginationNumberInvalid,
}, },
{ {
name: "1st page", name: "1st page",
@ -900,7 +900,7 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv {
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "bad layer push", resp, http.StatusBadRequest) checkResponse(t, "bad layer push", resp, http.StatusBadRequest)
checkBodyHasErrorCodes(t, "bad layer push", resp, v2.ErrorCodeDigestInvalid) checkBodyHasErrorCodes(t, "bad layer push", resp, errcode.ErrorCodeDigestInvalid)
// ----------------------------------------- // -----------------------------------------
// Do layer push with an empty body and correct digest // Do layer push with an empty body and correct digest
@ -1342,7 +1342,7 @@ func TestManifestAPI_DeleteTag_Unknown(t *testing.T) {
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, msg, resp, http.StatusNotFound) checkResponse(t, msg, resp, http.StatusNotFound)
checkBodyHasErrorCodes(t, msg, resp, v2.ErrorCodeManifestUnknown) checkBodyHasErrorCodes(t, msg, resp, errcode.ErrorCodeManifestUnknown)
} }
func TestManifestAPI_DeleteTag_ReadOnly(t *testing.T) { func TestManifestAPI_DeleteTag_ReadOnly(t *testing.T) {
@ -1442,7 +1442,7 @@ func TestGetManifestWithStorageError(t *testing.T) {
defer env1.Shutdown() defer env1.Shutdown()
repo, _ := reference.WithName(repositoryWithManifestNotFound) repo, _ := reference.WithName(repositoryWithManifestNotFound)
testManifestWithStorageError(t, env1, repo, http.StatusNotFound, v2.ErrorCodeManifestUnknown) testManifestWithStorageError(t, env1, repo, http.StatusNotFound, errcode.ErrorCodeManifestUnknown)
repo, _ = reference.WithName(repositoryWithGenericStorageError) repo, _ = reference.WithName(repositoryWithGenericStorageError)
testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown) testManifestWithStorageError(t, env1, repo, http.StatusInternalServerError, errcode.ErrorCodeUnknown)
@ -1528,7 +1528,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "getting non-existent manifest", resp, http.StatusNotFound) checkResponse(t, "getting non-existent manifest", resp, http.StatusNotFound)
checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, v2.ErrorCodeManifestUnknown) checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, errcode.ErrorCodeManifestUnknown)
tagsURL, err := env.builder.BuildTagsURL(imageName) tagsURL, err := env.builder.BuildTagsURL(imageName)
if err != nil { if err != nil {
@ -1543,7 +1543,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
// Check that we get an unknown repository error when asking for tags // Check that we get an unknown repository error when asking for tags
checkResponse(t, "getting unknown manifest tags", resp, http.StatusNotFound) checkResponse(t, "getting unknown manifest tags", resp, http.StatusNotFound)
checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, v2.ErrorCodeNameUnknown) checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, errcode.ErrorCodeNameUnknown)
// -------------------------------- // --------------------------------
// Attempt to push manifest with missing config and missing layers // Attempt to push manifest with missing config and missing layers
@ -1574,10 +1574,10 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
resp = putManifest(t, "putting missing config manifest", manifestURL, schema2.MediaTypeManifest, manifest) resp = putManifest(t, "putting missing config manifest", manifestURL, schema2.MediaTypeManifest, manifest)
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "putting missing config manifest", resp, http.StatusBadRequest) checkResponse(t, "putting missing config manifest", resp, http.StatusBadRequest)
_, p, counts := checkBodyHasErrorCodes(t, "putting missing config manifest", resp, v2.ErrorCodeManifestBlobUnknown) _, p, counts := checkBodyHasErrorCodes(t, "putting missing config manifest", resp, errcode.ErrorCodeManifestBlobUnknown)
expectedCounts := map[errcode.ErrorCode]int{ expectedCounts := map[errcode.ErrorCode]int{
v2.ErrorCodeManifestBlobUnknown: 3, errcode.ErrorCodeManifestBlobUnknown: 3,
} }
if !reflect.DeepEqual(counts, expectedCounts) { if !reflect.DeepEqual(counts, expectedCounts) {
@ -1616,10 +1616,10 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
resp = putManifest(t, "putting missing layer manifest", manifestURL, schema2.MediaTypeManifest, manifest) resp = putManifest(t, "putting missing layer manifest", manifestURL, schema2.MediaTypeManifest, manifest)
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "putting missing layer manifest", resp, http.StatusBadRequest) checkResponse(t, "putting missing layer manifest", resp, http.StatusBadRequest)
_, p, counts = checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, v2.ErrorCodeManifestBlobUnknown) _, p, counts = checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, errcode.ErrorCodeManifestBlobUnknown)
expectedCounts = map[errcode.ErrorCode]int{ expectedCounts = map[errcode.ErrorCode]int{
v2.ErrorCodeManifestBlobUnknown: 2, errcode.ErrorCodeManifestBlobUnknown: 2,
} }
if !reflect.DeepEqual(counts, expectedCounts) { if !reflect.DeepEqual(counts, expectedCounts) {
@ -1840,10 +1840,10 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
resp := putManifest(t, "putting missing manifest manifestlist", manifestURL, manifestlist.MediaTypeManifestList, manifestList) resp := putManifest(t, "putting missing manifest manifestlist", manifestURL, manifestlist.MediaTypeManifestList, manifestList)
defer resp.Body.Close() defer resp.Body.Close()
checkResponse(t, "putting missing manifest manifestlist", resp, http.StatusBadRequest) checkResponse(t, "putting missing manifest manifestlist", resp, http.StatusBadRequest)
_, p, counts := checkBodyHasErrorCodes(t, "putting missing manifest manifestlist", resp, v2.ErrorCodeManifestBlobUnknown) _, p, counts := checkBodyHasErrorCodes(t, "putting missing manifest manifestlist", resp, errcode.ErrorCodeManifestBlobUnknown)
expectedCounts := map[errcode.ErrorCode]int{ expectedCounts := map[errcode.ErrorCode]int{
v2.ErrorCodeManifestBlobUnknown: 1, errcode.ErrorCodeManifestBlobUnknown: 1,
} }
if !reflect.DeepEqual(counts, expectedCounts) { if !reflect.DeepEqual(counts, expectedCounts) {

View file

@ -661,9 +661,9 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
switch err := err.(type) { switch err := err.(type) {
case distribution.ErrRepositoryUnknown: case distribution.ErrRepositoryUnknown:
context.Errors = append(context.Errors, v2.ErrorCodeNameUnknown.WithDetail(err)) context.Errors = append(context.Errors, errcode.ErrorCodeNameUnknown.WithDetail(err))
case distribution.ErrRepositoryNameInvalid: case distribution.ErrRepositoryNameInvalid:
context.Errors = append(context.Errors, v2.ErrorCodeNameInvalid.WithDetail(err)) context.Errors = append(context.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err))
case errcode.Error: case errcode.Error:
context.Errors = append(context.Errors, err) context.Errors = append(context.Errors, err)
} }

View file

@ -6,7 +6,6 @@ import (
"github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3"
"github.com/distribution/distribution/v3/context" "github.com/distribution/distribution/v3/context"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
@ -18,12 +17,12 @@ func blobDispatcher(ctx *Context, r *http.Request) http.Handler {
if err == errDigestNotAvailable { if err == errDigestNotAvailable {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) ctx.Errors = append(ctx.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
}) })
} }
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) ctx.Errors = append(ctx.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
}) })
} }
@ -59,7 +58,7 @@ func (bh *blobHandler) GetBlob(w http.ResponseWriter, r *http.Request) {
desc, err := blobs.Stat(bh, bh.Digest) desc, err := blobs.Stat(bh, bh.Digest)
if err != nil { if err != nil {
if err == distribution.ErrBlobUnknown { if err == distribution.ErrBlobUnknown {
bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown.WithDetail(bh.Digest)) bh.Errors = append(bh.Errors, errcode.ErrorCodeBlobUnknown.WithDetail(bh.Digest))
} else { } else {
bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -85,7 +84,7 @@ func (bh *blobHandler) DeleteBlob(w http.ResponseWriter, r *http.Request) {
bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported) bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported)
return return
case distribution.ErrBlobUnknown: case distribution.ErrBlobUnknown:
bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown) bh.Errors = append(bh.Errors, errcode.ErrorCodeBlobUnknown)
return return
default: default:
bh.Errors = append(bh.Errors, err) bh.Errors = append(bh.Errors, err)

View file

@ -9,7 +9,6 @@ import (
"github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3"
dcontext "github.com/distribution/distribution/v3/context" dcontext "github.com/distribution/distribution/v3/context"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/distribution/distribution/v3/registry/storage" "github.com/distribution/distribution/v3/registry/storage"
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
@ -110,7 +109,7 @@ func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Req
upload, err := blobs.Resume(buh, buh.UUID) upload, err := blobs.Resume(buh, buh.UUID)
if err != nil { if err != nil {
if err == distribution.ErrBlobUploadUnknown { if err == distribution.ErrBlobUploadUnknown {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown.WithDetail(err))
} else { } else {
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -131,7 +130,7 @@ func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Req
// PatchBlobData writes data to an upload. // PatchBlobData writes data to an upload.
func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Request) { func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Request) {
if buh.Upload == nil { if buh.Upload == nil {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
return return
} }
@ -151,7 +150,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
return return
} }
if start > end || start != buh.Upload.Size() { if start > end || start != buh.Upload.Size() {
buh.Errors = append(buh.Errors, v2.ErrorCodeRangeInvalid) buh.Errors = append(buh.Errors, errcode.ErrorCodeRangeInvalid)
return return
} }
@ -161,7 +160,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
return return
} }
if clInt != (end-start)+1 { if clInt != (end-start)+1 {
buh.Errors = append(buh.Errors, v2.ErrorCodeSizeInvalid) buh.Errors = append(buh.Errors, errcode.ErrorCodeSizeInvalid)
return return
} }
} }
@ -186,7 +185,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
// url of the blob. // url of the blob.
func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *http.Request) { func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *http.Request) {
if buh.Upload == nil { if buh.Upload == nil {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
return return
} }
defer buh.Upload.Close() defer buh.Upload.Close()
@ -195,14 +194,14 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
if dgstStr == "" { if dgstStr == "" {
// no digest? return error, but allow retry. // no digest? return error, but allow retry.
buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail("digest missing")) buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail("digest missing"))
return return
} }
dgst, err := digest.Parse(dgstStr) dgst, err := digest.Parse(dgstStr)
if err != nil { if err != nil {
// no digest? return error, but allow retry. // no digest? return error, but allow retry.
buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail("digest parsing failed")) buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail("digest parsing failed"))
return return
} }
@ -221,7 +220,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
if err != nil { if err != nil {
switch err := err.(type) { switch err := err.(type) {
case distribution.ErrBlobInvalidDigest: case distribution.ErrBlobInvalidDigest:
buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeDigestInvalid.WithDetail(err))
case errcode.Error: case errcode.Error:
buh.Errors = append(buh.Errors, err) buh.Errors = append(buh.Errors, err)
default: default:
@ -231,7 +230,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
case distribution.ErrUnsupported: case distribution.ErrUnsupported:
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnsupported) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnsupported)
case distribution.ErrBlobInvalidLength, distribution.ErrBlobDigestUnsupported: case distribution.ErrBlobInvalidLength, distribution.ErrBlobDigestUnsupported:
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
default: default:
dcontext.GetLogger(buh).Errorf("unknown error completing upload: %v", err) dcontext.GetLogger(buh).Errorf("unknown error completing upload: %v", err)
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
@ -256,7 +255,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
// CancelBlobUpload cancels an in-progress upload of a blob. // CancelBlobUpload cancels an in-progress upload of a blob.
func (buh *blobUploadHandler) CancelBlobUpload(w http.ResponseWriter, r *http.Request) { func (buh *blobUploadHandler) CancelBlobUpload(w http.ResponseWriter, r *http.Request) {
if buh.Upload == nil { if buh.Upload == nil {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown)
return return
} }
defer buh.Upload.Close() defer buh.Upload.Close()
@ -275,7 +274,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
if err != nil { if err != nil {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
dcontext.GetLogger(ctx).Infof("error resolving upload: %v", err) dcontext.GetLogger(ctx).Infof("error resolving upload: %v", err)
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
}) })
} }
buh.State = state buh.State = state
@ -283,14 +282,14 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
if state.Name != ctx.Repository.Named().Name() { if state.Name != ctx.Repository.Named().Name() {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
dcontext.GetLogger(ctx).Infof("mismatched repository name in upload state: %q != %q", state.Name, buh.Repository.Named().Name()) dcontext.GetLogger(ctx).Infof("mismatched repository name in upload state: %q != %q", state.Name, buh.Repository.Named().Name())
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
}) })
} }
if state.UUID != buh.UUID { if state.UUID != buh.UUID {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
dcontext.GetLogger(ctx).Infof("mismatched uuid in upload state: %q != %q", state.UUID, buh.UUID) dcontext.GetLogger(ctx).Infof("mismatched uuid in upload state: %q != %q", state.UUID, buh.UUID)
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadInvalid.WithDetail(err))
}) })
} }
@ -300,7 +299,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
dcontext.GetLogger(ctx).Errorf("error resolving upload: %v", err) dcontext.GetLogger(ctx).Errorf("error resolving upload: %v", err)
if err == distribution.ErrBlobUploadUnknown { if err == distribution.ErrBlobUploadUnknown {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeBlobUploadUnknown.WithDetail(err))
}) })
} }
@ -313,7 +312,7 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
if size := upload.Size(); size != buh.State.Offset { if size := upload.Size(); size != buh.State.Offset {
dcontext.GetLogger(ctx).Errorf("upload resumed at wrong offset: %d != %d", size, buh.State.Offset) dcontext.GetLogger(ctx).Errorf("upload resumed at wrong offset: %d != %d", size, buh.State.Offset)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buh.Errors = append(buh.Errors, v2.ErrorCodeRangeInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeRangeInvalid.WithDetail(err))
}) })
} }
return nil return nil

View file

@ -9,7 +9,6 @@ import (
"strconv" "strconv"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/distribution/distribution/v3/registry/storage/driver" "github.com/distribution/distribution/v3/registry/storage/driver"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
) )
@ -47,13 +46,13 @@ func (ch *catalogHandler) GetCatalog(w http.ResponseWriter, r *http.Request) {
if n := q.Get("n"); n != "" { if n := q.Get("n"); n != "" {
parsedMax, err := strconv.Atoi(n) parsedMax, err := strconv.Atoi(n)
if err != nil || parsedMax < 0 { if err != nil || parsedMax < 0 {
ch.Errors = append(ch.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n})) ch.Errors = append(ch.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
return return
} }
// if a client requests more than it's allowed to receive // if a client requests more than it's allowed to receive
if parsedMax > maximumConfiguredEntries { if parsedMax > maximumConfiguredEntries {
ch.Errors = append(ch.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax})) ch.Errors = append(ch.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax}))
return return
} }
entries = parsedMax entries = parsedMax

View file

@ -13,7 +13,6 @@ import (
"github.com/distribution/distribution/v3/manifest/ocischema" "github.com/distribution/distribution/v3/manifest/ocischema"
"github.com/distribution/distribution/v3/manifest/schema2" "github.com/distribution/distribution/v3/manifest/schema2"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/distribution/distribution/v3/registry/auth" "github.com/distribution/distribution/v3/registry/auth"
"github.com/distribution/distribution/v3/registry/storage/driver" "github.com/distribution/distribution/v3/registry/storage/driver"
"github.com/distribution/reference" "github.com/distribution/reference"
@ -119,7 +118,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
desc, err := tags.Get(imh, imh.Tag) desc, err := tags.Get(imh, imh.Tag)
if err != nil { if err != nil {
if _, ok := err.(distribution.ErrTagUnknown); ok { if _, ok := err.(distribution.ErrTagUnknown); ok {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
} else { } else {
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -140,7 +139,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
manifest, err := manifests.Get(imh, imh.Digest, options...) manifest, err := manifests.Get(imh, imh.Digest, options...)
if err != nil { if err != nil {
if _, ok := err.(distribution.ErrManifestUnknownRevision); ok { if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
} else { } else {
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -160,11 +159,11 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
} }
if manifestType == ociSchema && !supports[ociSchema] { if manifestType == ociSchema && !supports[ociSchema] {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithMessage("OCI manifest found, but accept header does not support OCI manifests")) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithMessage("OCI manifest found, but accept header does not support OCI manifests"))
return return
} }
if manifestType == ociImageIndexSchema && !supports[ociImageIndexSchema] { if manifestType == ociImageIndexSchema && !supports[ociImageIndexSchema] {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithMessage("OCI index found, but accept header does not support OCI indexes")) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithMessage("OCI index found, but accept header does not support OCI indexes"))
return return
} }
@ -183,14 +182,14 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
} }
if manifestDigest == "" { if manifestDigest == "" {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown)
return return
} }
manifest, err = manifests.Get(imh, manifestDigest) manifest, err = manifests.Get(imh, manifestDigest)
if err != nil { if err != nil {
if _, ok := err.(distribution.ErrManifestUnknownRevision); ok { if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
} else { } else {
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -198,7 +197,7 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
} }
if _, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 && !supports[manifestSchema2] { if _, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 && !supports[manifestSchema2] {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithMessage("Schema 2 manifest not supported by client")) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithMessage("Schema 2 manifest not supported by client"))
return return
} else { } else {
imh.Digest = manifestDigest imh.Digest = manifestDigest
@ -238,27 +237,27 @@ func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request)
var jsonBuf bytes.Buffer var jsonBuf bytes.Buffer
if err := copyFullPayload(imh, w, r, &jsonBuf, maxManifestBodySize, "image manifest PUT"); err != nil { if err := copyFullPayload(imh, w, r, &jsonBuf, maxManifestBodySize, "image manifest PUT"); err != nil {
// copyFullPayload reports the error if necessary // copyFullPayload reports the error if necessary
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err.Error())) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithDetail(err.Error()))
return return
} }
mediaType := r.Header.Get("Content-Type") mediaType := r.Header.Get("Content-Type")
manifest, desc, err := distribution.UnmarshalManifest(mediaType, jsonBuf.Bytes()) manifest, desc, err := distribution.UnmarshalManifest(mediaType, jsonBuf.Bytes())
if err != nil { if err != nil {
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestInvalid.WithDetail(err))
return return
} }
if imh.Digest != "" { if imh.Digest != "" {
if desc.Digest != imh.Digest { if desc.Digest != imh.Digest {
dcontext.GetLogger(imh).Errorf("payload digest does not match: %q != %q", desc.Digest, imh.Digest) dcontext.GetLogger(imh).Errorf("payload digest does not match: %q != %q", desc.Digest, imh.Digest)
imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid) imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
return return
} }
} else if imh.Tag != "" { } else if imh.Tag != "" {
imh.Digest = desc.Digest imh.Digest = desc.Digest
} else { } else {
imh.Errors = append(imh.Errors, v2.ErrorCodeTagInvalid.WithDetail("no tag or digest specified")) imh.Errors = append(imh.Errors, errcode.ErrorCodeTagInvalid.WithDetail("no tag or digest specified"))
return return
} }
@ -297,14 +296,14 @@ func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request)
for _, verificationError := range err { for _, verificationError := range err {
switch verificationError := verificationError.(type) { switch verificationError := verificationError.(type) {
case distribution.ErrManifestBlobUnknown: case distribution.ErrManifestBlobUnknown:
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestBlobUnknown.WithDetail(verificationError.Digest)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestBlobUnknown.WithDetail(verificationError.Digest))
case distribution.ErrManifestNameInvalid: case distribution.ErrManifestNameInvalid:
imh.Errors = append(imh.Errors, v2.ErrorCodeNameInvalid.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err))
case distribution.ErrManifestUnverified: case distribution.ErrManifestUnverified:
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnverified) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnverified)
default: default:
if verificationError == digest.ErrDigestInvalidFormat { if verificationError == digest.ErrDigestInvalidFormat {
imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid) imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
} else { } else {
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown, verificationError) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown, verificationError)
} }
@ -434,7 +433,7 @@ func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Reques
if err := tagService.Untag(imh.Context, imh.Tag); err != nil { if err := tagService.Untag(imh.Context, imh.Tag); err != nil {
switch err.(type) { switch err.(type) {
case distribution.ErrTagUnknown, driver.PathNotFoundError: case distribution.ErrTagUnknown, driver.PathNotFoundError:
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown.WithDetail(err))
default: default:
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
} }
@ -455,10 +454,10 @@ func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Reques
switch err { switch err {
case digest.ErrDigestUnsupported: case digest.ErrDigestUnsupported:
case digest.ErrDigestInvalidFormat: case digest.ErrDigestInvalidFormat:
imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid) imh.Errors = append(imh.Errors, errcode.ErrorCodeDigestInvalid)
return return
case distribution.ErrBlobUnknown: case distribution.ErrBlobUnknown:
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown) imh.Errors = append(imh.Errors, errcode.ErrorCodeManifestUnknown)
return return
case distribution.ErrUnsupported: case distribution.ErrUnsupported:
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported) imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported)

View file

@ -8,7 +8,6 @@ import (
"github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3"
"github.com/distribution/distribution/v3/registry/api/errcode" "github.com/distribution/distribution/v3/registry/api/errcode"
v2 "github.com/distribution/distribution/v3/registry/api/v2"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
) )
@ -42,7 +41,7 @@ func (th *tagsHandler) GetTags(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
switch err := err.(type) { switch err := err.(type) {
case distribution.ErrRepositoryUnknown: case distribution.ErrRepositoryUnknown:
th.Errors = append(th.Errors, v2.ErrorCodeNameUnknown.WithDetail(map[string]string{"name": th.Repository.Named().Name()})) th.Errors = append(th.Errors, errcode.ErrorCodeNameUnknown.WithDetail(map[string]string{"name": th.Repository.Named().Name()}))
case errcode.Error: case errcode.Error:
th.Errors = append(th.Errors, err) th.Errors = append(th.Errors, err)
default: default:
@ -71,7 +70,7 @@ func (th *tagsHandler) GetTags(w http.ResponseWriter, r *http.Request) {
if n := q.Get("n"); n != "" { if n := q.Get("n"); n != "" {
maxEntries, err := strconv.Atoi(n) maxEntries, err := strconv.Atoi(n)
if err != nil || maxEntries < 0 { if err != nil || maxEntries < 0 {
th.Errors = append(th.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n})) th.Errors = append(th.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
return return
} }