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  }