github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/params/apierror.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package params
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"gopkg.in/macaroon.v1"
    11  )
    12  
    13  // UpgradeInProgressError signifies an upgrade is in progress.
    14  var UpgradeInProgressError = errors.New(CodeUpgradeInProgress)
    15  
    16  // Error is the type of error returned by any call to the state API.
    17  type Error struct {
    18  	Message string     `json:"message"`
    19  	Code    string     `json:"code"`
    20  	Info    *ErrorInfo `json:"info,omitempty"`
    21  }
    22  
    23  // ErrorInfo holds additional information provided by an error.
    24  // Note that although these fields are compatible with the
    25  // same fields in httpbakery.ErrorInfo, the Juju API server does
    26  // not implement endpoints directly compatible with that protocol
    27  // because the error response format varies according to
    28  // the endpoint.
    29  type ErrorInfo struct {
    30  	// Macaroon may hold a macaroon that, when
    31  	// discharged, may allow access to the juju API.
    32  	// This field is associated with the ErrDischargeRequired
    33  	// error code.
    34  	Macaroon *macaroon.Macaroon `json:"macaroon,omitempty"`
    35  
    36  	// MacaroonPath holds the URL path to be associated
    37  	// with the macaroon. The macaroon is potentially
    38  	// valid for all URLs under the given path.
    39  	// If it is empty, the macaroon will be associated with
    40  	// the original URL from which the error was returned.
    41  	MacaroonPath string `json:"macaroon-path,omitempty"`
    42  }
    43  
    44  func (e Error) Error() string {
    45  	return e.Message
    46  }
    47  
    48  func (e Error) ErrorCode() string {
    49  	return e.Code
    50  }
    51  
    52  // GoString implements fmt.GoStringer.  It means that a *Error shows its
    53  // contents correctly when printed with %#v.
    54  func (e Error) GoString() string {
    55  	return fmt.Sprintf("&params.Error{Message: %q, Code: %q}", e.Message, e.Code)
    56  }
    57  
    58  // The Code constants hold error codes for some kinds of error.
    59  const (
    60  	CodeNotFound                  = "not found"
    61  	CodeUserNotFound              = "user not found"
    62  	CodeModelNotFound             = "model not found"
    63  	CodeUnauthorized              = "unauthorized access"
    64  	CodeLoginExpired              = "login expired"
    65  	CodeNoCreds                   = "no credentials provided"
    66  	CodeCannotEnterScope          = "cannot enter scope"
    67  	CodeCannotEnterScopeYet       = "cannot enter scope yet"
    68  	CodeExcessiveContention       = "excessive contention"
    69  	CodeUnitHasSubordinates       = "unit has subordinates"
    70  	CodeNotAssigned               = "not assigned"
    71  	CodeStopped                   = "stopped"
    72  	CodeDead                      = "dead"
    73  	CodeHasAssignedUnits          = "machine has assigned units"
    74  	CodeHasHostedModels           = "controller has hosted models"
    75  	CodeMachineHasAttachedStorage = "machine has attached storage"
    76  	CodeNotProvisioned            = "not provisioned"
    77  	CodeNoAddressSet              = "no address set"
    78  	CodeTryAgain                  = "try again"
    79  	CodeNotImplemented            = "not implemented" // asserted to match rpc.codeNotImplemented in rpc/rpc_test.go
    80  	CodeAlreadyExists             = "already exists"
    81  	CodeUpgradeInProgress         = "upgrade in progress"
    82  	CodeActionNotAvailable        = "action no longer available"
    83  	CodeOperationBlocked          = "operation is blocked"
    84  	CodeLeadershipClaimDenied     = "leadership claim denied"
    85  	CodeLeaseClaimDenied          = "lease claim denied"
    86  	CodeNotSupported              = "not supported"
    87  	CodeBadRequest                = "bad request"
    88  	CodeMethodNotAllowed          = "method not allowed"
    89  	CodeForbidden                 = "forbidden"
    90  	CodeDischargeRequired         = "macaroon discharge required"
    91  	CodeRedirect                  = "redirection required"
    92  	CodeRetry                     = "retry"
    93  )
    94  
    95  // ErrCode returns the error code associated with
    96  // the given error, or the empty string if there
    97  // is none.
    98  func ErrCode(err error) string {
    99  	type ErrorCoder interface {
   100  		ErrorCode() string
   101  	}
   102  	switch err := errors.Cause(err).(type) {
   103  	case ErrorCoder:
   104  		return err.ErrorCode()
   105  	default:
   106  		return ""
   107  	}
   108  }
   109  
   110  func IsCodeActionNotAvailable(err error) bool {
   111  	return ErrCode(err) == CodeActionNotAvailable
   112  }
   113  
   114  func IsCodeNotFound(err error) bool {
   115  	return ErrCode(err) == CodeNotFound
   116  }
   117  
   118  func IsCodeUserNotFound(err error) bool {
   119  	return ErrCode(err) == CodeUserNotFound
   120  }
   121  
   122  func IsCodeModelNotFound(err error) bool {
   123  	return ErrCode(err) == CodeModelNotFound
   124  }
   125  
   126  func IsCodeUnauthorized(err error) bool {
   127  	return ErrCode(err) == CodeUnauthorized
   128  }
   129  
   130  func IsCodeNoCreds(err error) bool {
   131  	return ErrCode(err) == CodeNoCreds
   132  }
   133  
   134  func IsCodeLoginExpired(err error) bool {
   135  	return ErrCode(err) == CodeLoginExpired
   136  }
   137  
   138  // IsCodeNotFoundOrCodeUnauthorized is used in API clients which,
   139  // pre-API, used errors.IsNotFound; this is because an API client is
   140  // not necessarily privileged to know about the existence or otherwise
   141  // of a particular entity, and the server may hence convert NotFound
   142  // to Unauthorized at its discretion.
   143  func IsCodeNotFoundOrCodeUnauthorized(err error) bool {
   144  	return IsCodeNotFound(err) || IsCodeUnauthorized(err)
   145  }
   146  
   147  func IsCodeCannotEnterScope(err error) bool {
   148  	return ErrCode(err) == CodeCannotEnterScope
   149  }
   150  
   151  func IsCodeCannotEnterScopeYet(err error) bool {
   152  	return ErrCode(err) == CodeCannotEnterScopeYet
   153  }
   154  
   155  func IsCodeExcessiveContention(err error) bool {
   156  	return ErrCode(err) == CodeExcessiveContention
   157  }
   158  
   159  func IsCodeUnitHasSubordinates(err error) bool {
   160  	return ErrCode(err) == CodeUnitHasSubordinates
   161  }
   162  
   163  func IsCodeNotAssigned(err error) bool {
   164  	return ErrCode(err) == CodeNotAssigned
   165  }
   166  
   167  func IsCodeStopped(err error) bool {
   168  	return ErrCode(err) == CodeStopped
   169  }
   170  
   171  func IsCodeDead(err error) bool {
   172  	return ErrCode(err) == CodeDead
   173  }
   174  
   175  func IsCodeHasAssignedUnits(err error) bool {
   176  	return ErrCode(err) == CodeHasAssignedUnits
   177  }
   178  
   179  func IsCodeHasHostedModels(err error) bool {
   180  	return ErrCode(err) == CodeHasHostedModels
   181  }
   182  
   183  func IsCodeMachineHasAttachedStorage(err error) bool {
   184  	return ErrCode(err) == CodeMachineHasAttachedStorage
   185  }
   186  
   187  func IsCodeNotProvisioned(err error) bool {
   188  	return ErrCode(err) == CodeNotProvisioned
   189  }
   190  
   191  func IsCodeNoAddressSet(err error) bool {
   192  	return ErrCode(err) == CodeNoAddressSet
   193  }
   194  
   195  func IsCodeTryAgain(err error) bool {
   196  	return ErrCode(err) == CodeTryAgain
   197  }
   198  
   199  func IsCodeNotImplemented(err error) bool {
   200  	return ErrCode(err) == CodeNotImplemented
   201  }
   202  
   203  func IsCodeAlreadyExists(err error) bool {
   204  	return ErrCode(err) == CodeAlreadyExists
   205  }
   206  
   207  func IsCodeUpgradeInProgress(err error) bool {
   208  	return ErrCode(err) == CodeUpgradeInProgress
   209  }
   210  
   211  func IsCodeOperationBlocked(err error) bool {
   212  	return ErrCode(err) == CodeOperationBlocked
   213  }
   214  
   215  func IsCodeLeadershipClaimDenied(err error) bool {
   216  	return ErrCode(err) == CodeLeadershipClaimDenied
   217  }
   218  
   219  func IsCodeLeaseClaimDenied(err error) bool {
   220  	return ErrCode(err) == CodeLeaseClaimDenied
   221  }
   222  
   223  func IsCodeNotSupported(err error) bool {
   224  	return ErrCode(err) == CodeNotSupported
   225  }
   226  
   227  func IsBadRequest(err error) bool {
   228  	return ErrCode(err) == CodeBadRequest
   229  }
   230  
   231  func IsMethodNotAllowed(err error) bool {
   232  	return ErrCode(err) == CodeMethodNotAllowed
   233  }
   234  
   235  func IsRedirect(err error) bool {
   236  	return ErrCode(err) == CodeRedirect
   237  }