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("¶ms.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 }