github.com/containerd/Containerd@v1.4.13/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  }