github.com/christopherobin/docker@v1.6.2/registry/v2/errors.go (about) 1 package v2 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // ErrorCode represents the error type. The errors are serialized via strings 9 // and the integer format may change and should *never* be exported. 10 type ErrorCode int 11 12 const ( 13 // ErrorCodeUnknown is a catch-all for errors not defined below. 14 ErrorCodeUnknown ErrorCode = iota 15 16 // ErrorCodeDigestInvalid is returned when uploading a blob if the 17 // provided digest does not match the blob contents. 18 ErrorCodeDigestInvalid 19 20 // ErrorCodeSizeInvalid is returned when uploading a blob if the provided 21 // size does not match the content length. 22 ErrorCodeSizeInvalid 23 24 // ErrorCodeNameInvalid is returned when the name in the manifest does not 25 // match the provided name. 26 ErrorCodeNameInvalid 27 28 // ErrorCodeTagInvalid is returned when the tag in the manifest does not 29 // match the provided tag. 30 ErrorCodeTagInvalid 31 32 // ErrorCodeNameUnknown when the repository name is not known. 33 ErrorCodeNameUnknown 34 35 // ErrorCodeManifestUnknown returned when image manifest is unknown. 36 ErrorCodeManifestUnknown 37 38 // ErrorCodeManifestInvalid returned when an image manifest is invalid, 39 // typically during a PUT operation. This error encompasses all errors 40 // encountered during manifest validation that aren't signature errors. 41 ErrorCodeManifestInvalid 42 43 // ErrorCodeManifestUnverified is returned when the manifest fails 44 // signature verfication. 45 ErrorCodeManifestUnverified 46 47 // ErrorCodeBlobUnknown is returned when a blob is unknown to the 48 // registry. This can happen when the manifest references a nonexistent 49 // layer or the result is not found by a blob fetch. 50 ErrorCodeBlobUnknown 51 52 // ErrorCodeBlobUploadUnknown is returned when an upload is unknown. 53 ErrorCodeBlobUploadUnknown 54 ) 55 56 // ParseErrorCode attempts to parse the error code string, returning 57 // ErrorCodeUnknown if the error is not known. 58 func ParseErrorCode(s string) ErrorCode { 59 desc, ok := idToDescriptors[s] 60 61 if !ok { 62 return ErrorCodeUnknown 63 } 64 65 return desc.Code 66 } 67 68 // Descriptor returns the descriptor for the error code. 69 func (ec ErrorCode) Descriptor() ErrorDescriptor { 70 d, ok := errorCodeToDescriptors[ec] 71 72 if !ok { 73 return ErrorCodeUnknown.Descriptor() 74 } 75 76 return d 77 } 78 79 // String returns the canonical identifier for this error code. 80 func (ec ErrorCode) String() string { 81 return ec.Descriptor().Value 82 } 83 84 // Message returned the human-readable error message for this error code. 85 func (ec ErrorCode) Message() string { 86 return ec.Descriptor().Message 87 } 88 89 // MarshalText encodes the receiver into UTF-8-encoded text and returns the 90 // result. 91 func (ec ErrorCode) MarshalText() (text []byte, err error) { 92 return []byte(ec.String()), nil 93 } 94 95 // UnmarshalText decodes the form generated by MarshalText. 96 func (ec *ErrorCode) UnmarshalText(text []byte) error { 97 desc, ok := idToDescriptors[string(text)] 98 99 if !ok { 100 desc = ErrorCodeUnknown.Descriptor() 101 } 102 103 *ec = desc.Code 104 105 return nil 106 } 107 108 // Error provides a wrapper around ErrorCode with extra Details provided. 109 type Error struct { 110 Code ErrorCode `json:"code"` 111 Message string `json:"message,omitempty"` 112 Detail interface{} `json:"detail,omitempty"` 113 } 114 115 // Error returns a human readable representation of the error. 116 func (e Error) Error() string { 117 return fmt.Sprintf("%s: %s", 118 strings.ToLower(strings.Replace(e.Code.String(), "_", " ", -1)), 119 e.Message) 120 } 121 122 // Errors provides the envelope for multiple errors and a few sugar methods 123 // for use within the application. 124 type Errors struct { 125 Errors []Error `json:"errors,omitempty"` 126 } 127 128 // Push pushes an error on to the error stack, with the optional detail 129 // argument. It is a programming error (ie panic) to push more than one 130 // detail at a time. 131 func (errs *Errors) Push(code ErrorCode, details ...interface{}) { 132 if len(details) > 1 { 133 panic("please specify zero or one detail items for this error") 134 } 135 136 var detail interface{} 137 if len(details) > 0 { 138 detail = details[0] 139 } 140 141 if err, ok := detail.(error); ok { 142 detail = err.Error() 143 } 144 145 errs.PushErr(Error{ 146 Code: code, 147 Message: code.Message(), 148 Detail: detail, 149 }) 150 } 151 152 // PushErr pushes an error interface onto the error stack. 153 func (errs *Errors) PushErr(err error) { 154 switch err.(type) { 155 case Error: 156 errs.Errors = append(errs.Errors, err.(Error)) 157 default: 158 errs.Errors = append(errs.Errors, Error{Message: err.Error()}) 159 } 160 } 161 162 func (errs *Errors) Error() string { 163 switch errs.Len() { 164 case 0: 165 return "<nil>" 166 case 1: 167 return errs.Errors[0].Error() 168 default: 169 msg := "errors:\n" 170 for _, err := range errs.Errors { 171 msg += err.Error() + "\n" 172 } 173 return msg 174 } 175 } 176 177 // Clear clears the errors. 178 func (errs *Errors) Clear() { 179 errs.Errors = errs.Errors[:0] 180 } 181 182 // Len returns the current number of errors. 183 func (errs *Errors) Len() int { 184 return len(errs.Errors) 185 }