github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/remotes/docker/errdesc.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package docker 18 19 import ( 20 "fmt" 21 "net/http" 22 "sort" 23 "sync" 24 ) 25 26 var ( 27 errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{} 28 idToDescriptors = map[string]ErrorDescriptor{} 29 groupToDescriptors = map[string][]ErrorDescriptor{} 30 ) 31 32 var ( 33 // ErrorCodeUnknown is a generic error that can be used as a last 34 // resort if there is no situation-specific error message that can be used 35 ErrorCodeUnknown = Register("errcode", ErrorDescriptor{ 36 Value: "UNKNOWN", 37 Message: "unknown error", 38 Description: `Generic error returned when the error does not have an 39 API classification.`, 40 HTTPStatusCode: http.StatusInternalServerError, 41 }) 42 43 // ErrorCodeUnsupported is returned when an operation is not supported. 44 ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{ 45 Value: "UNSUPPORTED", 46 Message: "The operation is unsupported.", 47 Description: `The operation was unsupported due to a missing 48 implementation or invalid set of parameters.`, 49 HTTPStatusCode: http.StatusMethodNotAllowed, 50 }) 51 52 // ErrorCodeUnauthorized is returned if a request requires 53 // authentication. 54 ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{ 55 Value: "UNAUTHORIZED", 56 Message: "authentication required", 57 Description: `The access controller was unable to authenticate 58 the client. Often this will be accompanied by a 59 Www-Authenticate HTTP response header indicating how to 60 authenticate.`, 61 HTTPStatusCode: http.StatusUnauthorized, 62 }) 63 64 // ErrorCodeDenied is returned if a client does not have sufficient 65 // permission to perform an action. 66 ErrorCodeDenied = Register("errcode", ErrorDescriptor{ 67 Value: "DENIED", 68 Message: "requested access to the resource is denied", 69 Description: `The access controller denied access for the 70 operation on a resource.`, 71 HTTPStatusCode: http.StatusForbidden, 72 }) 73 74 // ErrorCodeUnavailable provides a common error to report unavailability 75 // of a service or endpoint. 76 ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ 77 Value: "UNAVAILABLE", 78 Message: "service unavailable", 79 Description: "Returned when a service is not available", 80 HTTPStatusCode: http.StatusServiceUnavailable, 81 }) 82 83 // ErrorCodeTooManyRequests is returned if a client attempts too many 84 // times to contact a service endpoint. 85 ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{ 86 Value: "TOOMANYREQUESTS", 87 Message: "too many requests", 88 Description: `Returned when a client attempts to contact a 89 service too many times`, 90 HTTPStatusCode: http.StatusTooManyRequests, 91 }) 92 ) 93 94 var nextCode = 1000 95 var registerLock sync.Mutex 96 97 // Register will make the passed-in error known to the environment and 98 // return a new ErrorCode 99 func Register(group string, descriptor ErrorDescriptor) ErrorCode { 100 registerLock.Lock() 101 defer registerLock.Unlock() 102 103 descriptor.Code = ErrorCode(nextCode) 104 105 if _, ok := idToDescriptors[descriptor.Value]; ok { 106 panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value)) 107 } 108 if _, ok := errorCodeToDescriptors[descriptor.Code]; ok { 109 panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code)) 110 } 111 112 groupToDescriptors[group] = append(groupToDescriptors[group], descriptor) 113 errorCodeToDescriptors[descriptor.Code] = descriptor 114 idToDescriptors[descriptor.Value] = descriptor 115 116 nextCode++ 117 return descriptor.Code 118 } 119 120 type byValue []ErrorDescriptor 121 122 func (a byValue) Len() int { return len(a) } 123 func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 124 func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value } 125 126 // GetGroupNames returns the list of Error group names that are registered 127 func GetGroupNames() []string { 128 keys := []string{} 129 130 for k := range groupToDescriptors { 131 keys = append(keys, k) 132 } 133 sort.Strings(keys) 134 return keys 135 } 136 137 // GetErrorCodeGroup returns the named group of error descriptors 138 func GetErrorCodeGroup(name string) []ErrorDescriptor { 139 desc := groupToDescriptors[name] 140 sort.Sort(byValue(desc)) 141 return desc 142 } 143 144 // GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are 145 // registered, irrespective of what group they're in 146 func GetErrorAllDescriptors() []ErrorDescriptor { 147 result := []ErrorDescriptor{} 148 149 for _, group := range GetGroupNames() { 150 result = append(result, GetErrorCodeGroup(group)...) 151 } 152 sort.Sort(byValue(result)) 153 return result 154 }