github.com/daaku/docker@v1.5.0/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  }