github.com/leeclow-ops/gophercloud@v1.2.1/errors.go (about) 1 package gophercloud 2 3 import ( 4 "fmt" 5 "net/http" 6 "strings" 7 ) 8 9 // BaseError is an error type that all other error types embed. 10 type BaseError struct { 11 DefaultErrString string 12 Info string 13 } 14 15 func (e BaseError) Error() string { 16 e.DefaultErrString = "An error occurred while executing a Gophercloud request." 17 return e.choseErrString() 18 } 19 20 func (e BaseError) choseErrString() string { 21 if e.Info != "" { 22 return e.Info 23 } 24 return e.DefaultErrString 25 } 26 27 // ErrMissingInput is the error when input is required in a particular 28 // situation but not provided by the user 29 type ErrMissingInput struct { 30 BaseError 31 Argument string 32 } 33 34 func (e ErrMissingInput) Error() string { 35 e.DefaultErrString = fmt.Sprintf("Missing input for argument [%s]", e.Argument) 36 return e.choseErrString() 37 } 38 39 // ErrInvalidInput is an error type used for most non-HTTP Gophercloud errors. 40 type ErrInvalidInput struct { 41 ErrMissingInput 42 Value interface{} 43 } 44 45 func (e ErrInvalidInput) Error() string { 46 e.DefaultErrString = fmt.Sprintf("Invalid input provided for argument [%s]: [%+v]", e.Argument, e.Value) 47 return e.choseErrString() 48 } 49 50 // ErrMissingEnvironmentVariable is the error when environment variable is required 51 // in a particular situation but not provided by the user 52 type ErrMissingEnvironmentVariable struct { 53 BaseError 54 EnvironmentVariable string 55 } 56 57 func (e ErrMissingEnvironmentVariable) Error() string { 58 e.DefaultErrString = fmt.Sprintf("Missing environment variable [%s]", e.EnvironmentVariable) 59 return e.choseErrString() 60 } 61 62 // ErrMissingAnyoneOfEnvironmentVariables is the error when anyone of the environment variables 63 // is required in a particular situation but not provided by the user 64 type ErrMissingAnyoneOfEnvironmentVariables struct { 65 BaseError 66 EnvironmentVariables []string 67 } 68 69 func (e ErrMissingAnyoneOfEnvironmentVariables) Error() string { 70 e.DefaultErrString = fmt.Sprintf( 71 "Missing one of the following environment variables [%s]", 72 strings.Join(e.EnvironmentVariables, ", "), 73 ) 74 return e.choseErrString() 75 } 76 77 // ErrUnexpectedResponseCode is returned by the Request method when a response code other than 78 // those listed in OkCodes is encountered. 79 type ErrUnexpectedResponseCode struct { 80 BaseError 81 URL string 82 Method string 83 Expected []int 84 Actual int 85 Body []byte 86 ResponseHeader http.Header 87 } 88 89 func (e ErrUnexpectedResponseCode) Error() string { 90 e.DefaultErrString = fmt.Sprintf( 91 "Expected HTTP response code %v when accessing [%s %s], but got %d instead\n%s", 92 e.Expected, e.Method, e.URL, e.Actual, e.Body, 93 ) 94 return e.choseErrString() 95 } 96 97 // GetStatusCode returns the actual status code of the error. 98 func (e ErrUnexpectedResponseCode) GetStatusCode() int { 99 return e.Actual 100 } 101 102 // StatusCodeError is a convenience interface to easily allow access to the 103 // status code field of the various ErrDefault* types. 104 // 105 // By using this interface, you only have to make a single type cast of 106 // the returned error to err.(StatusCodeError) and then call GetStatusCode() 107 // instead of having a large switch statement checking for each of the 108 // ErrDefault* types. 109 type StatusCodeError interface { 110 Error() string 111 GetStatusCode() int 112 } 113 114 // ErrDefault400 is the default error type returned on a 400 HTTP response code. 115 type ErrDefault400 struct { 116 ErrUnexpectedResponseCode 117 } 118 119 // ErrDefault401 is the default error type returned on a 401 HTTP response code. 120 type ErrDefault401 struct { 121 ErrUnexpectedResponseCode 122 } 123 124 // ErrDefault403 is the default error type returned on a 403 HTTP response code. 125 type ErrDefault403 struct { 126 ErrUnexpectedResponseCode 127 } 128 129 // ErrDefault404 is the default error type returned on a 404 HTTP response code. 130 type ErrDefault404 struct { 131 ErrUnexpectedResponseCode 132 } 133 134 // ErrDefault405 is the default error type returned on a 405 HTTP response code. 135 type ErrDefault405 struct { 136 ErrUnexpectedResponseCode 137 } 138 139 // ErrDefault408 is the default error type returned on a 408 HTTP response code. 140 type ErrDefault408 struct { 141 ErrUnexpectedResponseCode 142 } 143 144 // ErrDefault409 is the default error type returned on a 409 HTTP response code. 145 type ErrDefault409 struct { 146 ErrUnexpectedResponseCode 147 } 148 149 // ErrDefault429 is the default error type returned on a 429 HTTP response code. 150 type ErrDefault429 struct { 151 ErrUnexpectedResponseCode 152 } 153 154 // ErrDefault500 is the default error type returned on a 500 HTTP response code. 155 type ErrDefault500 struct { 156 ErrUnexpectedResponseCode 157 } 158 159 // ErrDefault502 is the default error type returned on a 502 HTTP response code. 160 type ErrDefault502 struct { 161 ErrUnexpectedResponseCode 162 } 163 164 // ErrDefault503 is the default error type returned on a 503 HTTP response code. 165 type ErrDefault503 struct { 166 ErrUnexpectedResponseCode 167 } 168 169 // ErrDefault504 is the default error type returned on a 504 HTTP response code. 170 type ErrDefault504 struct { 171 ErrUnexpectedResponseCode 172 } 173 174 func (e ErrDefault400) Error() string { 175 e.DefaultErrString = fmt.Sprintf( 176 "Bad request with: [%s %s], error message: %s", 177 e.Method, e.URL, e.Body, 178 ) 179 return e.choseErrString() 180 } 181 func (e ErrDefault401) Error() string { 182 return "Authentication failed" 183 } 184 func (e ErrDefault403) Error() string { 185 e.DefaultErrString = fmt.Sprintf( 186 "Request forbidden: [%s %s], error message: %s", 187 e.Method, e.URL, e.Body, 188 ) 189 return e.choseErrString() 190 } 191 func (e ErrDefault404) Error() string { 192 e.DefaultErrString = fmt.Sprintf( 193 "Resource not found: [%s %s], error message: %s", 194 e.Method, e.URL, e.Body, 195 ) 196 return e.choseErrString() 197 } 198 func (e ErrDefault405) Error() string { 199 return "Method not allowed" 200 } 201 func (e ErrDefault408) Error() string { 202 return "The server timed out waiting for the request" 203 } 204 func (e ErrDefault429) Error() string { 205 return "Too many requests have been sent in a given amount of time. Pause" + 206 " requests, wait up to one minute, and try again." 207 } 208 func (e ErrDefault500) Error() string { 209 return "Internal Server Error" 210 } 211 func (e ErrDefault502) Error() string { 212 return "Bad Gateway" 213 } 214 func (e ErrDefault503) Error() string { 215 return "The service is currently unable to handle the request due to a temporary" + 216 " overloading or maintenance. This is a temporary condition. Try again later." 217 } 218 func (e ErrDefault504) Error() string { 219 return "Gateway Timeout" 220 } 221 222 // Err400er is the interface resource error types implement to override the error message 223 // from a 400 error. 224 type Err400er interface { 225 Error400(ErrUnexpectedResponseCode) error 226 } 227 228 // Err401er is the interface resource error types implement to override the error message 229 // from a 401 error. 230 type Err401er interface { 231 Error401(ErrUnexpectedResponseCode) error 232 } 233 234 // Err403er is the interface resource error types implement to override the error message 235 // from a 403 error. 236 type Err403er interface { 237 Error403(ErrUnexpectedResponseCode) error 238 } 239 240 // Err404er is the interface resource error types implement to override the error message 241 // from a 404 error. 242 type Err404er interface { 243 Error404(ErrUnexpectedResponseCode) error 244 } 245 246 // Err405er is the interface resource error types implement to override the error message 247 // from a 405 error. 248 type Err405er interface { 249 Error405(ErrUnexpectedResponseCode) error 250 } 251 252 // Err408er is the interface resource error types implement to override the error message 253 // from a 408 error. 254 type Err408er interface { 255 Error408(ErrUnexpectedResponseCode) error 256 } 257 258 // Err409er is the interface resource error types implement to override the error message 259 // from a 409 error. 260 type Err409er interface { 261 Error409(ErrUnexpectedResponseCode) error 262 } 263 264 // Err429er is the interface resource error types implement to override the error message 265 // from a 429 error. 266 type Err429er interface { 267 Error429(ErrUnexpectedResponseCode) error 268 } 269 270 // Err500er is the interface resource error types implement to override the error message 271 // from a 500 error. 272 type Err500er interface { 273 Error500(ErrUnexpectedResponseCode) error 274 } 275 276 // Err502er is the interface resource error types implement to override the error message 277 // from a 502 error. 278 type Err502er interface { 279 Error502(ErrUnexpectedResponseCode) error 280 } 281 282 // Err503er is the interface resource error types implement to override the error message 283 // from a 503 error. 284 type Err503er interface { 285 Error503(ErrUnexpectedResponseCode) error 286 } 287 288 // Err504er is the interface resource error types implement to override the error message 289 // from a 504 error. 290 type Err504er interface { 291 Error504(ErrUnexpectedResponseCode) error 292 } 293 294 // ErrTimeOut is the error type returned when an operations times out. 295 type ErrTimeOut struct { 296 BaseError 297 } 298 299 func (e ErrTimeOut) Error() string { 300 e.DefaultErrString = "A time out occurred" 301 return e.choseErrString() 302 } 303 304 // ErrUnableToReauthenticate is the error type returned when reauthentication fails. 305 type ErrUnableToReauthenticate struct { 306 BaseError 307 ErrOriginal error 308 ErrReauth error 309 } 310 311 func (e ErrUnableToReauthenticate) Error() string { 312 e.DefaultErrString = fmt.Sprintf("Unable to re-authenticate: %s: %s", e.ErrOriginal, e.ErrReauth) 313 return e.choseErrString() 314 } 315 316 // ErrErrorAfterReauthentication is the error type returned when reauthentication 317 // succeeds, but an error occurs afterword (usually an HTTP error). 318 type ErrErrorAfterReauthentication struct { 319 BaseError 320 ErrOriginal error 321 } 322 323 func (e ErrErrorAfterReauthentication) Error() string { 324 e.DefaultErrString = fmt.Sprintf("Successfully re-authenticated, but got error executing request: %s", e.ErrOriginal) 325 return e.choseErrString() 326 } 327 328 // ErrServiceNotFound is returned when no service in a service catalog matches 329 // the provided EndpointOpts. This is generally returned by provider service 330 // factory methods like "NewComputeV2()" and can mean that a service is not 331 // enabled for your account. 332 type ErrServiceNotFound struct { 333 BaseError 334 } 335 336 func (e ErrServiceNotFound) Error() string { 337 e.DefaultErrString = "No suitable service could be found in the service catalog." 338 return e.choseErrString() 339 } 340 341 // ErrEndpointNotFound is returned when no available endpoints match the 342 // provided EndpointOpts. This is also generally returned by provider service 343 // factory methods, and usually indicates that a region was specified 344 // incorrectly. 345 type ErrEndpointNotFound struct { 346 BaseError 347 } 348 349 func (e ErrEndpointNotFound) Error() string { 350 e.DefaultErrString = "No suitable endpoint could be found in the service catalog." 351 return e.choseErrString() 352 } 353 354 // ErrResourceNotFound is the error when trying to retrieve a resource's 355 // ID by name and the resource doesn't exist. 356 type ErrResourceNotFound struct { 357 BaseError 358 Name string 359 ResourceType string 360 } 361 362 func (e ErrResourceNotFound) Error() string { 363 e.DefaultErrString = fmt.Sprintf("Unable to find %s with name %s", e.ResourceType, e.Name) 364 return e.choseErrString() 365 } 366 367 // ErrMultipleResourcesFound is the error when trying to retrieve a resource's 368 // ID by name and multiple resources have the user-provided name. 369 type ErrMultipleResourcesFound struct { 370 BaseError 371 Name string 372 Count int 373 ResourceType string 374 } 375 376 func (e ErrMultipleResourcesFound) Error() string { 377 e.DefaultErrString = fmt.Sprintf("Found %d %ss matching %s", e.Count, e.ResourceType, e.Name) 378 return e.choseErrString() 379 } 380 381 // ErrUnexpectedType is the error when an unexpected type is encountered 382 type ErrUnexpectedType struct { 383 BaseError 384 Expected string 385 Actual string 386 } 387 388 func (e ErrUnexpectedType) Error() string { 389 e.DefaultErrString = fmt.Sprintf("Expected %s but got %s", e.Expected, e.Actual) 390 return e.choseErrString() 391 } 392 393 func unacceptedAttributeErr(attribute string) string { 394 return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute) 395 } 396 397 func redundantWithTokenErr(attribute string) string { 398 return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute) 399 } 400 401 func redundantWithUserID(attribute string) string { 402 return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute) 403 } 404 405 // ErrAPIKeyProvided indicates that an APIKey was provided but can't be used. 406 type ErrAPIKeyProvided struct{ BaseError } 407 408 func (e ErrAPIKeyProvided) Error() string { 409 return unacceptedAttributeErr("APIKey") 410 } 411 412 // ErrTenantIDProvided indicates that a TenantID was provided but can't be used. 413 type ErrTenantIDProvided struct{ BaseError } 414 415 func (e ErrTenantIDProvided) Error() string { 416 return unacceptedAttributeErr("TenantID") 417 } 418 419 // ErrTenantNameProvided indicates that a TenantName was provided but can't be used. 420 type ErrTenantNameProvided struct{ BaseError } 421 422 func (e ErrTenantNameProvided) Error() string { 423 return unacceptedAttributeErr("TenantName") 424 } 425 426 // ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead. 427 type ErrUsernameWithToken struct{ BaseError } 428 429 func (e ErrUsernameWithToken) Error() string { 430 return redundantWithTokenErr("Username") 431 } 432 433 // ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead. 434 type ErrUserIDWithToken struct{ BaseError } 435 436 func (e ErrUserIDWithToken) Error() string { 437 return redundantWithTokenErr("UserID") 438 } 439 440 // ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead. 441 type ErrDomainIDWithToken struct{ BaseError } 442 443 func (e ErrDomainIDWithToken) Error() string { 444 return redundantWithTokenErr("DomainID") 445 } 446 447 // ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s 448 type ErrDomainNameWithToken struct{ BaseError } 449 450 func (e ErrDomainNameWithToken) Error() string { 451 return redundantWithTokenErr("DomainName") 452 } 453 454 // ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once. 455 type ErrUsernameOrUserID struct{ BaseError } 456 457 func (e ErrUsernameOrUserID) Error() string { 458 return "Exactly one of Username and UserID must be provided for password authentication" 459 } 460 461 // ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used. 462 type ErrDomainIDWithUserID struct{ BaseError } 463 464 func (e ErrDomainIDWithUserID) Error() string { 465 return redundantWithUserID("DomainID") 466 } 467 468 // ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used. 469 type ErrDomainNameWithUserID struct{ BaseError } 470 471 func (e ErrDomainNameWithUserID) Error() string { 472 return redundantWithUserID("DomainName") 473 } 474 475 // ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it. 476 // It may also indicate that both a DomainID and a DomainName were provided at once. 477 type ErrDomainIDOrDomainName struct{ BaseError } 478 479 func (e ErrDomainIDOrDomainName) Error() string { 480 return "You must provide exactly one of DomainID or DomainName to authenticate by Username" 481 } 482 483 // ErrMissingPassword indicates that no password was provided and no token is available. 484 type ErrMissingPassword struct{ BaseError } 485 486 func (e ErrMissingPassword) Error() string { 487 return "You must provide a password to authenticate" 488 } 489 490 // ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present. 491 type ErrScopeDomainIDOrDomainName struct{ BaseError } 492 493 func (e ErrScopeDomainIDOrDomainName) Error() string { 494 return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName" 495 } 496 497 // ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope. 498 type ErrScopeProjectIDOrProjectName struct{ BaseError } 499 500 func (e ErrScopeProjectIDOrProjectName) Error() string { 501 return "You must provide at most one of ProjectID or ProjectName in a Scope" 502 } 503 504 // ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope. 505 type ErrScopeProjectIDAlone struct{ BaseError } 506 507 func (e ErrScopeProjectIDAlone) Error() string { 508 return "ProjectID must be supplied alone in a Scope" 509 } 510 511 // ErrScopeEmpty indicates that no credentials were provided in a Scope. 512 type ErrScopeEmpty struct{ BaseError } 513 514 func (e ErrScopeEmpty) Error() string { 515 return "You must provide either a Project or Domain in a Scope" 516 } 517 518 // ErrAppCredMissingSecret indicates that no Application Credential Secret was provided with Application Credential ID or Name 519 type ErrAppCredMissingSecret struct{ BaseError } 520 521 func (e ErrAppCredMissingSecret) Error() string { 522 return "You must provide an Application Credential Secret" 523 }