github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/api/errcode/register.go (about) 1 package errcode 2 3 import ( 4 "fmt" 5 "net/http" 6 "sort" 7 "sync" 8 ) 9 10 var ( 11 errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{} 12 idToDescriptors = map[string]ErrorDescriptor{} 13 groupToDescriptors = map[string][]ErrorDescriptor{} 14 ) 15 16 var ( 17 // ErrorCodeUnknown is a generic error that can be used as a last 18 // resort if there is no situation-specific error message that can be used 19 ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ 20 Value: "UNKNOWN", 21 Message: "unknown error", 22 Description: `Generic error returned when the error does not have an 23 API classification.`, 24 HTTPStatusCode: http.StatusInternalServerError, 25 }) 26 27 // ErrorCodeUnsupported is returned when an operation is not supported. 28 ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ 29 Value: "UNSUPPORTED", 30 Message: "The operation is unsupported.", 31 Description: `The operation was unsupported due to a missing 32 implementation or invalid set of parameters.`, 33 HTTPStatusCode: http.StatusMethodNotAllowed, 34 }) 35 36 // ErrorCodeUnauthorized is returned if a request requires 37 // authentication. 38 ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ 39 Value: "UNAUTHORIZED", 40 Message: "authentication required", 41 Description: `The access controller was unable to authenticate 42 the client. Often this will be accompanied by a 43 Www-Authenticate HTTP response header indicating how to 44 authenticate.`, 45 HTTPStatusCode: http.StatusUnauthorized, 46 }) 47 48 // ErrorCodeDenied is returned if a client does not have sufficient 49 // permission to perform an action. 50 ErrorCodeDenied = Register("errcode", ErrorDescriptor{ 51 Value: "DENIED", 52 Message: "requested access to the resource is denied", 53 Description: `The access controller denied access for the 54 operation on a resource.`, 55 HTTPStatusCode: http.StatusForbidden, 56 }) 57 58 // ErrorCodeUnavailable provides a common error to report unavialability 59 // of a service or endpoint. 60 ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ 61 Value: "UNAVAILABLE", 62 Message: "service unavailable", 63 Description: "Returned when a service is not available", 64 HTTPStatusCode: http.StatusServiceUnavailable, 65 }) 66 ) 67 68 var nextCode = 1000 69 var registerLock sync.Mutex 70 71 // Register will make the passed-in error known to the environment and 72 // return a new ErrorCode 73 func Register(group string, descriptor ErrorDescriptor) ErrorCode { 74 registerLock.Lock() 75 defer registerLock.Unlock() 76 77 descriptor.Code = ErrorCode(nextCode) 78 79 if _, ok := idToDescriptors[descriptor.Value]; ok { 80 panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value)) 81 } 82 if _, ok := errorCodeToDescriptors[descriptor.Code]; ok { 83 panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code)) 84 } 85 86 groupToDescriptors[group] = append(groupToDescriptors[group], descriptor) 87 errorCodeToDescriptors[descriptor.Code] = descriptor 88 idToDescriptors[descriptor.Value] = descriptor 89 90 nextCode++ 91 return descriptor.Code 92 } 93 94 type byValue []ErrorDescriptor 95 96 func (a byValue) Len() int { return len(a) } 97 func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 98 func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value } 99 100 // GetGroupNames returns the list of Error group names that are registered 101 func GetGroupNames() []string { 102 keys := []string{} 103 104 for k := range groupToDescriptors { 105 keys = append(keys, k) 106 } 107 sort.Strings(keys) 108 return keys 109 } 110 111 // GetErrorCodeGroup returns the named group of error descriptors 112 func GetErrorCodeGroup(name string) []ErrorDescriptor { 113 desc := groupToDescriptors[name] 114 sort.Sort(byValue(desc)) 115 return desc 116 } 117 118 // GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are 119 // registered, irrespective of what group they're in 120 func GetErrorAllDescriptors() []ErrorDescriptor { 121 result := []ErrorDescriptor{} 122 123 for _, group := range GetGroupNames() { 124 result = append(result, GetErrorCodeGroup(group)...) 125 } 126 sort.Sort(byValue(result)) 127 return result 128 }