github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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
    19  	Code    string
    20  	Info    *ErrorInfo `json:",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:",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:",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  	CodeUnauthorized              = "unauthorized access"
    62  	CodeCannotEnterScope          = "cannot enter scope"
    63  	CodeCannotEnterScopeYet       = "cannot enter scope yet"
    64  	CodeExcessiveContention       = "excessive contention"
    65  	CodeUnitHasSubordinates       = "unit has subordinates"
    66  	CodeNotAssigned               = "not assigned"
    67  	CodeStopped                   = "stopped"
    68  	CodeDead                      = "dead"
    69  	CodeHasAssignedUnits          = "machine has assigned units"
    70  	CodeHasHostedModels           = "controller has hosted models"
    71  	CodeMachineHasAttachedStorage = "machine has attached storage"
    72  	CodeNotProvisioned            = "not provisioned"
    73  	CodeNoAddressSet              = "no address set"
    74  	CodeTryAgain                  = "try again"
    75  	CodeNotImplemented            = "not implemented" // asserted to match rpc.codeNotImplemented in rpc/rpc_test.go
    76  	CodeAlreadyExists             = "already exists"
    77  	CodeUpgradeInProgress         = "upgrade in progress"
    78  	CodeActionNotAvailable        = "action no longer available"
    79  	CodeOperationBlocked          = "operation is blocked"
    80  	CodeLeadershipClaimDenied     = "leadership claim denied"
    81  	CodeLeaseClaimDenied          = "lease claim denied"
    82  	CodeNotSupported              = "not supported"
    83  	CodeBadRequest                = "bad request"
    84  	CodeMethodNotAllowed          = "method not allowed"
    85  	CodeForbidden                 = "forbidden"
    86  	CodeDischargeRequired         = "macaroon discharge required"
    87  )
    88  
    89  // ErrCode returns the error code associated with
    90  // the given error, or the empty string if there
    91  // is none.
    92  func ErrCode(err error) string {
    93  	type ErrorCoder interface {
    94  		ErrorCode() string
    95  	}
    96  	switch err := errors.Cause(err).(type) {
    97  	case ErrorCoder:
    98  		return err.ErrorCode()
    99  	default:
   100  		return ""
   101  	}
   102  }
   103  
   104  func IsCodeActionNotAvailable(err error) bool {
   105  	return ErrCode(err) == CodeActionNotAvailable
   106  }
   107  
   108  func IsCodeNotFound(err error) bool {
   109  	return ErrCode(err) == CodeNotFound
   110  }
   111  
   112  func IsCodeUnauthorized(err error) bool {
   113  	return ErrCode(err) == CodeUnauthorized
   114  }
   115  
   116  // IsCodeNotFoundOrCodeUnauthorized is used in API clients which,
   117  // pre-API, used errors.IsNotFound; this is because an API client is
   118  // not necessarily privileged to know about the existence or otherwise
   119  // of a particular entity, and the server may hence convert NotFound
   120  // to Unauthorized at its discretion.
   121  func IsCodeNotFoundOrCodeUnauthorized(err error) bool {
   122  	return IsCodeNotFound(err) || IsCodeUnauthorized(err)
   123  }
   124  
   125  func IsCodeCannotEnterScope(err error) bool {
   126  	return ErrCode(err) == CodeCannotEnterScope
   127  }
   128  
   129  func IsCodeCannotEnterScopeYet(err error) bool {
   130  	return ErrCode(err) == CodeCannotEnterScopeYet
   131  }
   132  
   133  func IsCodeExcessiveContention(err error) bool {
   134  	return ErrCode(err) == CodeExcessiveContention
   135  }
   136  
   137  func IsCodeUnitHasSubordinates(err error) bool {
   138  	return ErrCode(err) == CodeUnitHasSubordinates
   139  }
   140  
   141  func IsCodeNotAssigned(err error) bool {
   142  	return ErrCode(err) == CodeNotAssigned
   143  }
   144  
   145  func IsCodeStopped(err error) bool {
   146  	return ErrCode(err) == CodeStopped
   147  }
   148  
   149  func IsCodeDead(err error) bool {
   150  	return ErrCode(err) == CodeDead
   151  }
   152  
   153  func IsCodeHasAssignedUnits(err error) bool {
   154  	return ErrCode(err) == CodeHasAssignedUnits
   155  }
   156  
   157  func IsCodeHasHostedModels(err error) bool {
   158  	return ErrCode(err) == CodeHasHostedModels
   159  }
   160  
   161  func IsCodeMachineHasAttachedStorage(err error) bool {
   162  	return ErrCode(err) == CodeMachineHasAttachedStorage
   163  }
   164  
   165  func IsCodeNotProvisioned(err error) bool {
   166  	return ErrCode(err) == CodeNotProvisioned
   167  }
   168  
   169  func IsCodeNoAddressSet(err error) bool {
   170  	return ErrCode(err) == CodeNoAddressSet
   171  }
   172  
   173  func IsCodeTryAgain(err error) bool {
   174  	return ErrCode(err) == CodeTryAgain
   175  }
   176  
   177  func IsCodeNotImplemented(err error) bool {
   178  	return ErrCode(err) == CodeNotImplemented
   179  }
   180  
   181  func IsCodeAlreadyExists(err error) bool {
   182  	return ErrCode(err) == CodeAlreadyExists
   183  }
   184  
   185  func IsCodeUpgradeInProgress(err error) bool {
   186  	return ErrCode(err) == CodeUpgradeInProgress
   187  }
   188  
   189  func IsCodeOperationBlocked(err error) bool {
   190  	return ErrCode(err) == CodeOperationBlocked
   191  }
   192  
   193  func IsCodeLeadershipClaimDenied(err error) bool {
   194  	return ErrCode(err) == CodeLeadershipClaimDenied
   195  }
   196  
   197  func IsCodeLeaseClaimDenied(err error) bool {
   198  	return ErrCode(err) == CodeLeaseClaimDenied
   199  }
   200  
   201  func IsCodeNotSupported(err error) bool {
   202  	return ErrCode(err) == CodeNotSupported
   203  }
   204  
   205  func IsBadRequest(err error) bool {
   206  	return ErrCode(err) == CodeBadRequest
   207  }
   208  
   209  func IsMethodNotAllowed(err error) bool {
   210  	return ErrCode(err) == CodeMethodNotAllowed
   211  }