From f141480d98ee592575565607ecce7644eddf5137 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Thu, 6 Aug 2015 16:25:08 -0700 Subject: [PATCH] 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 --- cmd/registry-api-descriptor-template/main.go | 5 ++- docs/spec/api.md | 2 +- registry/api/errcode/register.go | 46 ++++++++++++++++---- registry/api/v2/descriptors.go | 20 ++++----- registry/api/v2/errors.go | 18 -------- registry/client/errors.go | 3 +- registry/client/repository_test.go | 5 +-- registry/handlers/app.go | 4 +- registry/handlers/app_test.go | 4 +- registry/handlers/blob.go | 2 +- registry/handlers/images.go | 2 +- registry/proxy/proxymanifeststore.go | 6 +-- 12 files changed, 65 insertions(+), 52 deletions(-) diff --git a/cmd/registry-api-descriptor-template/main.go b/cmd/registry-api-descriptor-template/main.go index 05a1b487..61eab8ec 100644 --- a/cmd/registry-api-descriptor-template/main.go +++ b/cmd/registry-api-descriptor-template/main.go @@ -50,7 +50,10 @@ func main() { ErrorDescriptors []errcode.ErrorDescriptor }{ 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 { diff --git a/docs/spec/api.md b/docs/spec/api.md index 9b56b6c5..40e21e41 100644 --- a/docs/spec/api.md +++ b/docs/spec/api.md @@ -2249,7 +2249,7 @@ The following headers will be returned with the response: |Name|Description| |----|-----------| -|`Content-Length`|Zero| +|`Content-Length`|0| |`Docker-Content-Digest`|Digest of the targeted content for the request.| diff --git a/registry/api/errcode/register.go b/registry/api/errcode/register.go index 42f911b3..e1c93f38 100644 --- a/registry/api/errcode/register.go +++ b/registry/api/errcode/register.go @@ -13,15 +13,45 @@ var ( groupToDescriptors = map[string][]ErrorDescriptor{} ) -// 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 -var ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ - Value: "UNKNOWN", - Message: "unknown error", - Description: `Generic error returned when the error does not have an +var ( + // 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 + ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ + Value: "UNKNOWN", + Message: "unknown error", + Description: `Generic error returned when the error does not have an 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 registerLock sync.Mutex diff --git a/registry/api/v2/descriptors.go b/registry/api/v2/descriptors.go index 0ef64f88..09289b96 100644 --- a/registry/api/v2/descriptors.go +++ b/registry/api/v2/descriptors.go @@ -124,7 +124,7 @@ var ( }, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, Body: BodyDescriptor{ ContentType: "application/json; charset=utf-8", @@ -145,7 +145,7 @@ var ( }, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, Body: BodyDescriptor{ ContentType: "application/json; charset=utf-8", @@ -374,7 +374,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, }, { @@ -451,7 +451,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, }, }, @@ -506,7 +506,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, }, }, @@ -568,7 +568,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, }, { @@ -645,7 +645,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, }, { @@ -682,7 +682,7 @@ var routeDescriptors = []RouteDescriptor{ }, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, Body: BodyDescriptor{ ContentType: "application/json; charset=utf-8", @@ -737,7 +737,7 @@ var routeDescriptors = []RouteDescriptor{ }, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnauthorized, + errcode.ErrorCodeUnauthorized, }, Body: BodyDescriptor{ ContentType: "application/json; charset=utf-8", @@ -974,7 +974,7 @@ var routeDescriptors = []RouteDescriptor{ Format: errorsBody, }, ErrorCodes: []errcode.ErrorCode{ - ErrorCodeUnsupported, + errcode.ErrorCodeUnsupported, }, }, }, diff --git a/registry/api/v2/errors.go b/registry/api/v2/errors.go index 87e27f2e..ece52a2c 100644 --- a/registry/api/v2/errors.go +++ b/registry/api/v2/errors.go @@ -9,24 +9,6 @@ import ( const errGroup = "registry.api.v2" 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 // provided digest does not match the blob contents. ErrorCodeDigestInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ diff --git a/registry/client/errors.go b/registry/client/errors.go index ebd1c36c..7305c021 100644 --- a/registry/client/errors.go +++ b/registry/client/errors.go @@ -8,7 +8,6 @@ import ( "net/http" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" ) // UnexpectedHTTPStatusError is returned when an unexpected HTTP status is @@ -52,7 +51,7 @@ func handleErrorResponse(resp *http.Response) error { if resp.StatusCode == 401 { err := parseHTTPErrorResponse(resp.Body) if uErr, ok := err.(*UnexpectedHTTPResponseError); ok { - return v2.ErrorCodeUnauthorized.WithDetail(uErr.Response) + return errcode.ErrorCodeUnauthorized.WithDetail(uErr.Response) } return err } diff --git a/registry/client/repository_test.go b/registry/client/repository_test.go index 26201763..8a7a598e 100644 --- a/registry/client/repository_test.go +++ b/registry/client/repository_test.go @@ -21,7 +21,6 @@ import ( "github.com/docker/distribution/digest" "github.com/docker/distribution/manifest" "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/testutil" ) @@ -782,10 +781,10 @@ func TestManifestUnauthorized(t *testing.T) { if !ok { 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()) } - 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) } } diff --git a/registry/handlers/app.go b/registry/handlers/app.go index ab33e8a6..11d91120 100644 --- a/registry/handlers/app.go +++ b/registry/handlers/app.go @@ -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 // that mistake elsewhere in the code, allowing any operation to // 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) } 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 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) } default: diff --git a/registry/handlers/app_test.go b/registry/handlers/app_test.go index 6f597527..3ef2342c 100644 --- a/registry/handlers/app_test.go +++ b/registry/handlers/app_test.go @@ -205,8 +205,8 @@ func TestNewApp(t *testing.T) { if !ok { t.Fatalf("not an ErrorCoder: %#v", errs[0]) } - if err2.ErrorCode() != v2.ErrorCodeUnauthorized { - t.Fatalf("unexpected error code: %v != %v", err2.ErrorCode(), v2.ErrorCodeUnauthorized) + if err2.ErrorCode() != errcode.ErrorCodeUnauthorized { + t.Fatalf("unexpected error code: %v != %v", err2.ErrorCode(), errcode.ErrorCodeUnauthorized) } } diff --git a/registry/handlers/blob.go b/registry/handlers/blob.go index b7c06ea2..fd514ec0 100644 --- a/registry/handlers/blob.go +++ b/registry/handlers/blob.go @@ -81,7 +81,7 @@ func (bh *blobHandler) DeleteBlob(w http.ResponseWriter, r *http.Request) { bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown) case distribution.ErrUnsupported: w.WriteHeader(http.StatusMethodNotAllowed) - bh.Errors = append(bh.Errors, v2.ErrorCodeUnsupported) + bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported) default: bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown) } diff --git a/registry/handlers/images.go b/registry/handlers/images.go index dbe7b706..f5354399 100644 --- a/registry/handlers/images.go +++ b/registry/handlers/images.go @@ -213,7 +213,7 @@ func (imh *imageManifestHandler) DeleteImageManifest(w http.ResponseWriter, r *h w.WriteHeader(http.StatusNotFound) return case distribution.ErrUnsupported: - imh.Errors = append(imh.Errors, v2.ErrorCodeUnsupported) + imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported) w.WriteHeader(http.StatusMethodNotAllowed) default: imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown) diff --git a/registry/proxy/proxymanifeststore.go b/registry/proxy/proxymanifeststore.go index 5b79c8ce..8921998a 100644 --- a/registry/proxy/proxymanifeststore.go +++ b/registry/proxy/proxymanifeststore.go @@ -7,7 +7,7 @@ import ( "github.com/docker/distribution/context" "github.com/docker/distribution/digest" "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/proxy/scheduler" ) @@ -147,9 +147,9 @@ func manifestDigest(sm *manifest.SignedManifest) (digest.Digest, error) { } func (pms proxyManifestStore) Put(manifest *manifest.SignedManifest) error { - return v2.ErrorCodeUnsupported + return errcode.ErrorCodeUnsupported } func (pms proxyManifestStore) Delete(dgst digest.Digest) error { - return v2.ErrorCodeUnsupported + return errcode.ErrorCodeUnsupported }