diff --git a/errors.go b/errors.go index 9a28e5b6..e2f16ba0 100644 --- a/errors.go +++ b/errors.go @@ -17,20 +17,14 @@ const ( // The following errors can happen during a layer upload. - // ErrorCodeInvalidChecksum is returned when uploading a layer if the - // provided checksum does not match the layer contents. - ErrorCodeInvalidChecksum + // ErrorCodeInvalidDigest is returned when uploading a layer if the + // provided digest does not match the layer contents. + ErrorCodeInvalidDigest // ErrorCodeInvalidLength is returned when uploading a layer if the provided // length does not match the content length. ErrorCodeInvalidLength - // ErrorCodeInvalidTarsum is returned when the provided tarsum does not - // match the computed tarsum of the contents. - ErrorCodeInvalidTarsum - - // The following errors can happen during manifest upload. - // ErrorCodeInvalidName is returned when the name in the manifest does not // match the provided name. ErrorCodeInvalidName @@ -47,6 +41,9 @@ const ( // nonexistent layer. ErrorCodeUnknownLayer + // ErrorCodeUnknownLayerUpload is returned when an upload is accessed. + ErrorCodeUnknownLayerUpload + // ErrorCodeUntrustedSignature is returned when the manifest is signed by an // untrusted source. ErrorCodeUntrustedSignature @@ -54,25 +51,25 @@ const ( var errorCodeStrings = map[ErrorCode]string{ ErrorCodeUnknown: "UNKNOWN", - ErrorCodeInvalidChecksum: "INVALID_CHECKSUM", + ErrorCodeInvalidDigest: "INVALID_DIGEST", ErrorCodeInvalidLength: "INVALID_LENGTH", - ErrorCodeInvalidTarsum: "INVALID_TARSUM", ErrorCodeInvalidName: "INVALID_NAME", ErrorCodeInvalidTag: "INVALID_TAG", ErrorCodeUnverifiedManifest: "UNVERIFIED_MANIFEST", ErrorCodeUnknownLayer: "UNKNOWN_LAYER", + ErrorCodeUnknownLayerUpload: "UNKNOWN_LAYER_UPLOAD", ErrorCodeUntrustedSignature: "UNTRUSTED_SIGNATURE", } var errorCodesMessages = map[ErrorCode]string{ ErrorCodeUnknown: "unknown error", - ErrorCodeInvalidChecksum: "provided checksum did not match uploaded content", + ErrorCodeInvalidDigest: "provided digest did not match uploaded content", ErrorCodeInvalidLength: "provided length did not match content length", - ErrorCodeInvalidTarsum: "provided tarsum did not match binary content", ErrorCodeInvalidName: "Manifest name did not match URI", ErrorCodeInvalidTag: "Manifest tag did not match URI", ErrorCodeUnverifiedManifest: "Manifest failed signature validation", ErrorCodeUnknownLayer: "Referenced layer not available", + ErrorCodeUnknownLayerUpload: "cannot resume unknown layer upload", ErrorCodeUntrustedSignature: "Manifest signed by untrusted source", } @@ -136,7 +133,7 @@ func (ec *ErrorCode) UnmarshalText(text []byte) error { // Error provides a wrapper around ErrorCode with extra Details provided. type Error struct { - Code ErrorCode `json:"code,omitempty"` + Code ErrorCode `json:"code"` Message string `json:"message,omitempty"` Detail interface{} `json:"detail,omitempty"` } @@ -144,7 +141,7 @@ type Error struct { // Error returns a human readable representation of the error. func (e Error) Error() string { return fmt.Sprintf("%s: %s", - strings.Title(strings.Replace(e.Code.String(), "_", " ", -1)), + strings.ToLower(strings.Replace(e.Code.String(), "_", " ", -1)), e.Message) } @@ -167,6 +164,10 @@ func (errs *Errors) Push(code ErrorCode, details ...interface{}) { detail = details[0] } + if err, ok := detail.(error); ok { + detail = err.Error() + } + errs.PushErr(Error{ Code: code, Message: code.Message(), @@ -180,7 +181,7 @@ func (errs *Errors) PushErr(err error) { } func (errs *Errors) Error() string { - switch len(errs.Errors) { + switch errs.Len() { case 0: return "" case 1: @@ -194,6 +195,16 @@ func (errs *Errors) Error() string { } } +// Clear clears the errors. +func (errs *Errors) Clear() { + errs.Errors = errs.Errors[:0] +} + +// Len returns the current number of errors. +func (errs *Errors) Len() int { + return len(errs.Errors) +} + // DetailUnknownLayer provides detail for unknown layer errors, returned by // image manifest push for layers that are not yet transferred. This intended // to only be used on the backend to return detail for this specific error. diff --git a/errors_test.go b/errors_test.go index e6ec72f9..709b6ced 100644 --- a/errors_test.go +++ b/errors_test.go @@ -56,7 +56,7 @@ func TestErrorCodes(t *testing.T) { func TestErrorsManagement(t *testing.T) { var errs Errors - errs.Push(ErrorCodeInvalidChecksum) + errs.Push(ErrorCodeInvalidDigest) var detail DetailUnknownLayer detail.Unknown.BlobSum = "sometestblobsumdoesntmatter" @@ -69,7 +69,20 @@ func TestErrorsManagement(t *testing.T) { t.Fatalf("error marashaling errors: %v", err) } - expectedJSON := "{\"errors\":[{\"code\":\"INVALID_CHECKSUM\",\"message\":\"provided checksum did not match uploaded content\"},{\"code\":\"UNKNOWN_LAYER\",\"message\":\"Referenced layer not available\",\"detail\":{\"unknown\":{\"blobSum\":\"sometestblobsumdoesntmatter\"}}}]}" + expectedJSON := "{\"errors\":[{\"code\":\"INVALID_DIGEST\",\"message\":\"provided digest did not match uploaded content\"},{\"code\":\"UNKNOWN_LAYER\",\"message\":\"Referenced layer not available\",\"detail\":{\"unknown\":{\"blobSum\":\"sometestblobsumdoesntmatter\"}}}]}" + + if string(p) != expectedJSON { + t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON) + } + + errs.Clear() + errs.Push(ErrorCodeUnknown) + expectedJSON = "{\"errors\":[{\"code\":\"UNKNOWN\",\"message\":\"unknown error\"}]}" + p, err = json.Marshal(errs) + + if err != nil { + t.Fatalf("error marashaling errors: %v", err) + } if string(p) != expectedJSON { t.Fatalf("unexpected json: %q != %q", string(p), expectedJSON)