github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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("¶ms.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 }