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