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