Move common error codes to errcode package
Several error codes are generally useful but tied to the v2 specification definitions. This change moves these error code definitions into the common package for use by the health package, which is not tied to the v2 API. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
6ba799b69e
commit
f141480d98
12 changed files with 65 additions and 52 deletions
|
@ -50,7 +50,10 @@ func main() {
|
||||||
ErrorDescriptors []errcode.ErrorDescriptor
|
ErrorDescriptors []errcode.ErrorDescriptor
|
||||||
}{
|
}{
|
||||||
RouteDescriptors: v2.APIDescriptor.RouteDescriptors,
|
RouteDescriptors: v2.APIDescriptor.RouteDescriptors,
|
||||||
ErrorDescriptors: errcode.GetErrorCodeGroup("registry.api.v2"),
|
ErrorDescriptors: append(errcode.GetErrorCodeGroup("registry.api.v2"),
|
||||||
|
// The following are part of the specification but provided by errcode default.
|
||||||
|
errcode.ErrorCodeUnauthorized.Descriptor(),
|
||||||
|
errcode.ErrorCodeUnsupported.Descriptor()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tmpl.Execute(os.Stdout, data); err != nil {
|
if err := tmpl.Execute(os.Stdout, data); err != nil {
|
||||||
|
|
|
@ -2249,7 +2249,7 @@ The following headers will be returned with the response:
|
||||||
|
|
||||||
|Name|Description|
|
|Name|Description|
|
||||||
|----|-----------|
|
|----|-----------|
|
||||||
|`Content-Length`|Zero|
|
|`Content-Length`|0|
|
||||||
|`Docker-Content-Digest`|Digest of the targeted content for the request.|
|
|`Docker-Content-Digest`|Digest of the targeted content for the request.|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,45 @@ var (
|
||||||
groupToDescriptors = map[string][]ErrorDescriptor{}
|
groupToDescriptors = map[string][]ErrorDescriptor{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrorCodeUnknown is a generic error that can be used as a last
|
var (
|
||||||
// resort if there is no situation-specific error message that can be used
|
// ErrorCodeUnknown is a generic error that can be used as a last
|
||||||
var ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
|
// resort if there is no situation-specific error message that can be used
|
||||||
|
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
|
||||||
API classification.`,
|
API classification.`,
|
||||||
HTTPStatusCode: http.StatusInternalServerError,
|
HTTPStatusCode: http.StatusInternalServerError,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ErrorCodeUnsupported is returned when an operation is not supported.
|
||||||
|
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
|
||||||
|
Value: "UNSUPPORTED",
|
||||||
|
Message: "The operation is unsupported.",
|
||||||
|
Description: `The operation was unsupported due to a missing
|
||||||
|
implementation or invalid set of parameters.`,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
})
|
||||||
|
|
||||||
|
// ErrorCodeUnauthorized is returned if a request is not authorized.
|
||||||
|
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
|
||||||
|
Value: "UNAUTHORIZED",
|
||||||
|
Message: "access to the requested resource is not authorized",
|
||||||
|
Description: `The access controller denied access for the operation on
|
||||||
|
a resource. Often this will be accompanied by a 401 Unauthorized
|
||||||
|
response status.`,
|
||||||
|
HTTPStatusCode: http.StatusUnauthorized,
|
||||||
|
})
|
||||||
|
|
||||||
|
// ErrorCodeUnavailable provides a common error to report unavialability
|
||||||
|
// of a service or endpoint.
|
||||||
|
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
|
||||||
|
Value: "UNAVAILABLE",
|
||||||
|
Message: "service unavailable",
|
||||||
|
Description: "Returned when a service is not available",
|
||||||
|
HTTPStatusCode: http.StatusServiceUnavailable,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
var nextCode = 1000
|
var nextCode = 1000
|
||||||
var registerLock sync.Mutex
|
var registerLock sync.Mutex
|
||||||
|
|
|
@ -124,7 +124,7 @@ var (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
Body: BodyDescriptor{
|
Body: BodyDescriptor{
|
||||||
ContentType: "application/json; charset=utf-8",
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
@ -145,7 +145,7 @@ var (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
Body: BodyDescriptor{
|
Body: BodyDescriptor{
|
||||||
ContentType: "application/json; charset=utf-8",
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
@ -374,7 +374,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -451,7 +451,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -506,7 +506,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -568,7 +568,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -645,7 +645,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -682,7 +682,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
Body: BodyDescriptor{
|
Body: BodyDescriptor{
|
||||||
ContentType: "application/json; charset=utf-8",
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
@ -737,7 +737,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnauthorized,
|
errcode.ErrorCodeUnauthorized,
|
||||||
},
|
},
|
||||||
Body: BodyDescriptor{
|
Body: BodyDescriptor{
|
||||||
ContentType: "application/json; charset=utf-8",
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
@ -974,7 +974,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||||
Format: errorsBody,
|
Format: errorsBody,
|
||||||
},
|
},
|
||||||
ErrorCodes: []errcode.ErrorCode{
|
ErrorCodes: []errcode.ErrorCode{
|
||||||
ErrorCodeUnsupported,
|
errcode.ErrorCodeUnsupported,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,24 +9,6 @@ import (
|
||||||
const errGroup = "registry.api.v2"
|
const errGroup = "registry.api.v2"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrorCodeUnsupported is returned when an operation is not supported.
|
|
||||||
ErrorCodeUnsupported = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
|
||||||
Value: "UNSUPPORTED",
|
|
||||||
Message: "The operation is unsupported.",
|
|
||||||
Description: `The operation was unsupported due to a missing
|
|
||||||
implementation or invalid set of parameters.`,
|
|
||||||
})
|
|
||||||
|
|
||||||
// ErrorCodeUnauthorized is returned if a request is not authorized.
|
|
||||||
ErrorCodeUnauthorized = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
|
||||||
Value: "UNAUTHORIZED",
|
|
||||||
Message: "access to the requested resource is not authorized",
|
|
||||||
Description: `The access controller denied access for the operation on
|
|
||||||
a resource. Often this will be accompanied by a 401 Unauthorized
|
|
||||||
response status.`,
|
|
||||||
HTTPStatusCode: http.StatusUnauthorized,
|
|
||||||
})
|
|
||||||
|
|
||||||
// ErrorCodeDigestInvalid is returned when uploading a blob if the
|
// ErrorCodeDigestInvalid is returned when uploading a blob if the
|
||||||
// provided digest does not match the blob contents.
|
// provided digest does not match the blob contents.
|
||||||
ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
"github.com/docker/distribution/registry/api/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
|
// UnexpectedHTTPStatusError is returned when an unexpected HTTP status is
|
||||||
|
@ -52,7 +51,7 @@ func handleErrorResponse(resp *http.Response) error {
|
||||||
if resp.StatusCode == 401 {
|
if resp.StatusCode == 401 {
|
||||||
err := parseHTTPErrorResponse(resp.Body)
|
err := parseHTTPErrorResponse(resp.Body)
|
||||||
if uErr, ok := err.(*UnexpectedHTTPResponseError); ok {
|
if uErr, ok := err.(*UnexpectedHTTPResponseError); ok {
|
||||||
return v2.ErrorCodeUnauthorized.WithDetail(uErr.Response)
|
return errcode.ErrorCodeUnauthorized.WithDetail(uErr.Response)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/docker/distribution/digest"
|
"github.com/docker/distribution/digest"
|
||||||
"github.com/docker/distribution/manifest"
|
"github.com/docker/distribution/manifest"
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
"github.com/docker/distribution/registry/api/v2"
|
|
||||||
"github.com/docker/distribution/testutil"
|
"github.com/docker/distribution/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -782,10 +781,10 @@ func TestManifestUnauthorized(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("Unexpected error type: %#v", err)
|
t.Fatalf("Unexpected error type: %#v", err)
|
||||||
}
|
}
|
||||||
if v2Err.Code != v2.ErrorCodeUnauthorized {
|
if v2Err.Code != errcode.ErrorCodeUnauthorized {
|
||||||
t.Fatalf("Unexpected error code: %s", v2Err.Code.String())
|
t.Fatalf("Unexpected error code: %s", v2Err.Code.String())
|
||||||
}
|
}
|
||||||
if expected := v2.ErrorCodeUnauthorized.Message(); v2Err.Message != expected {
|
if expected := errcode.ErrorCodeUnauthorized.Message(); v2Err.Message != expected {
|
||||||
t.Fatalf("Unexpected message value: %q, expected %q", v2Err.Message, expected)
|
t.Fatalf("Unexpected message value: %q, expected %q", v2Err.Message, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -575,7 +575,7 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont
|
||||||
// base route is accessed. This section prevents us from making
|
// base route is accessed. This section prevents us from making
|
||||||
// that mistake elsewhere in the code, allowing any operation to
|
// that mistake elsewhere in the code, allowing any operation to
|
||||||
// proceed.
|
// proceed.
|
||||||
if err := errcode.ServeJSON(w, v2.ErrorCodeUnauthorized); err != nil {
|
if err := errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized); err != nil {
|
||||||
ctxu.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors)
|
ctxu.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("forbidden: no repository name")
|
return fmt.Errorf("forbidden: no repository name")
|
||||||
|
@ -590,7 +590,7 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont
|
||||||
// Add the appropriate WWW-Auth header
|
// Add the appropriate WWW-Auth header
|
||||||
err.SetHeaders(w)
|
err.SetHeaders(w)
|
||||||
|
|
||||||
if err := errcode.ServeJSON(w, v2.ErrorCodeUnauthorized.WithDetail(accessRecords)); err != nil {
|
if err := errcode.ServeJSON(w, errcode.ErrorCodeUnauthorized.WithDetail(accessRecords)); err != nil {
|
||||||
ctxu.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors)
|
ctxu.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -205,8 +205,8 @@ func TestNewApp(t *testing.T) {
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("not an ErrorCoder: %#v", errs[0])
|
t.Fatalf("not an ErrorCoder: %#v", errs[0])
|
||||||
}
|
}
|
||||||
if err2.ErrorCode() != v2.ErrorCodeUnauthorized {
|
if err2.ErrorCode() != errcode.ErrorCodeUnauthorized {
|
||||||
t.Fatalf("unexpected error code: %v != %v", err2.ErrorCode(), v2.ErrorCodeUnauthorized)
|
t.Fatalf("unexpected error code: %v != %v", err2.ErrorCode(), errcode.ErrorCodeUnauthorized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ func (bh *blobHandler) DeleteBlob(w http.ResponseWriter, r *http.Request) {
|
||||||
bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown)
|
bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown)
|
||||||
case distribution.ErrUnsupported:
|
case distribution.ErrUnsupported:
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
bh.Errors = append(bh.Errors, v2.ErrorCodeUnsupported)
|
bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported)
|
||||||
default:
|
default:
|
||||||
bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown)
|
bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown)
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ func (imh *imageManifestHandler) DeleteImageManifest(w http.ResponseWriter, r *h
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
case distribution.ErrUnsupported:
|
case distribution.ErrUnsupported:
|
||||||
imh.Errors = append(imh.Errors, v2.ErrorCodeUnsupported)
|
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported)
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
default:
|
default:
|
||||||
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown)
|
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/digest"
|
"github.com/docker/distribution/digest"
|
||||||
"github.com/docker/distribution/manifest"
|
"github.com/docker/distribution/manifest"
|
||||||
"github.com/docker/distribution/registry/api/v2"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
"github.com/docker/distribution/registry/client"
|
"github.com/docker/distribution/registry/client"
|
||||||
"github.com/docker/distribution/registry/proxy/scheduler"
|
"github.com/docker/distribution/registry/proxy/scheduler"
|
||||||
)
|
)
|
||||||
|
@ -147,9 +147,9 @@ func manifestDigest(sm *manifest.SignedManifest) (digest.Digest, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pms proxyManifestStore) Put(manifest *manifest.SignedManifest) error {
|
func (pms proxyManifestStore) Put(manifest *manifest.SignedManifest) error {
|
||||||
return v2.ErrorCodeUnsupported
|
return errcode.ErrorCodeUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pms proxyManifestStore) Delete(dgst digest.Digest) error {
|
func (pms proxyManifestStore) Delete(dgst digest.Digest) error {
|
||||||
return v2.ErrorCodeUnsupported
|
return errcode.ErrorCodeUnsupported
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue