github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/errors.go (about) 1 package gophercloud 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "net/http" 8 "strings" 9 ) 10 11 // BaseError is an error type that all other error types embed. 12 type BaseError struct { 13 DefaultErrString string 14 Info string 15 } 16 17 func (e BaseError) Error() string { 18 e.DefaultErrString = "An error occurred while executing a Gophercloud request." 19 return e.choseErrString() 20 } 21 22 func (e BaseError) choseErrString() string { 23 if e.Info != "" { 24 return e.Info 25 } 26 return e.DefaultErrString 27 } 28 29 // ErrMissingInput is the error when input is required in a particular 30 // situation but not provided by the user 31 type ErrMissingInput struct { 32 BaseError 33 Argument string 34 } 35 36 func (e ErrMissingInput) Error() string { 37 e.DefaultErrString = fmt.Sprintf("Missing input for argument [%s]", e.Argument) 38 return e.choseErrString() 39 } 40 41 // ErrInvalidInput is an error type used for most non-HTTP Gophercloud errors. 42 type ErrInvalidInput struct { 43 ErrMissingInput 44 Value any 45 } 46 47 func (e ErrInvalidInput) Error() string { 48 e.DefaultErrString = fmt.Sprintf("Invalid input provided for argument [%s]: [%+v]", e.Argument, e.Value) 49 return e.choseErrString() 50 } 51 52 // ErrMissingEnvironmentVariable is the error when environment variable is required 53 // in a particular situation but not provided by the user 54 type ErrMissingEnvironmentVariable struct { 55 BaseError 56 EnvironmentVariable string 57 } 58 59 func (e ErrMissingEnvironmentVariable) Error() string { 60 e.DefaultErrString = fmt.Sprintf("Missing environment variable [%s]", e.EnvironmentVariable) 61 return e.choseErrString() 62 } 63 64 // ErrMissingAnyoneOfEnvironmentVariables is the error when anyone of the environment variables 65 // is required in a particular situation but not provided by the user 66 type ErrMissingAnyoneOfEnvironmentVariables struct { 67 BaseError 68 EnvironmentVariables []string 69 } 70 71 func (e ErrMissingAnyoneOfEnvironmentVariables) Error() string { 72 e.DefaultErrString = fmt.Sprintf( 73 "Missing one of the following environment variables [%s]", 74 strings.Join(e.EnvironmentVariables, ", "), 75 ) 76 return e.choseErrString() 77 } 78 79 // ErrUnexpectedResponseCode is returned by the Request method when a response code other than 80 // those listed in OkCodes is encountered. 81 type ErrUnexpectedResponseCode struct { 82 BaseError 83 URL string 84 Method string 85 Expected []int 86 Actual int 87 Body []byte 88 ResponseHeader http.Header 89 } 90 91 func (e ErrUnexpectedResponseCode) Error() string { 92 e.DefaultErrString = fmt.Sprintf( 93 "Expected HTTP response code %v when accessing [%s %s], but got %d instead: %s", 94 e.Expected, e.Method, e.URL, e.Actual, bytes.TrimSpace(e.Body), 95 ) 96 return e.choseErrString() 97 } 98 99 // GetStatusCode returns the actual status code of the error. 100 func (e ErrUnexpectedResponseCode) GetStatusCode() int { 101 return e.Actual 102 } 103 104 // ResponseCodeIs returns true if this error is or contains an ErrUnexpectedResponseCode reporting 105 // that the request failed with the given response code. For example, this checks if a request 106 // failed because of a 404 error: 107 // 108 // allServers, err := servers.List(client, servers.ListOpts{}) 109 // if gophercloud.ResponseCodeIs(err, http.StatusNotFound) { 110 // handleNotFound() 111 // } 112 // 113 // It is safe to pass a nil error, in which case this function always returns false. 114 func ResponseCodeIs(err error, status int) bool { 115 var codeError ErrUnexpectedResponseCode 116 if errors.As(err, &codeError) { 117 return codeError.Actual == status 118 } 119 return false 120 } 121 122 // ErrTimeOut is the error type returned when an operations times out. 123 type ErrTimeOut struct { 124 BaseError 125 } 126 127 func (e ErrTimeOut) Error() string { 128 e.DefaultErrString = "A time out occurred" 129 return e.choseErrString() 130 } 131 132 // ErrUnableToReauthenticate is the error type returned when reauthentication fails. 133 type ErrUnableToReauthenticate struct { 134 BaseError 135 ErrOriginal error 136 ErrReauth error 137 } 138 139 func (e ErrUnableToReauthenticate) Error() string { 140 e.DefaultErrString = fmt.Sprintf("Unable to re-authenticate: %s: %s", e.ErrOriginal, e.ErrReauth) 141 return e.choseErrString() 142 } 143 144 // ErrErrorAfterReauthentication is the error type returned when reauthentication 145 // succeeds, but an error occurs afterword (usually an HTTP error). 146 type ErrErrorAfterReauthentication struct { 147 BaseError 148 ErrOriginal error 149 } 150 151 func (e ErrErrorAfterReauthentication) Error() string { 152 e.DefaultErrString = fmt.Sprintf("Successfully re-authenticated, but got error executing request: %s", e.ErrOriginal) 153 return e.choseErrString() 154 } 155 156 // ErrServiceNotFound is returned when no service in a service catalog matches 157 // the provided EndpointOpts. This is generally returned by provider service 158 // factory methods like "NewComputeV2()" and can mean that a service is not 159 // enabled for your account. 160 type ErrServiceNotFound struct { 161 BaseError 162 } 163 164 func (e ErrServiceNotFound) Error() string { 165 e.DefaultErrString = "No suitable service could be found in the service catalog." 166 return e.choseErrString() 167 } 168 169 // ErrEndpointNotFound is returned when no available endpoints match the 170 // provided EndpointOpts. This is also generally returned by provider service 171 // factory methods, and usually indicates that a region was specified 172 // incorrectly. 173 type ErrEndpointNotFound struct { 174 BaseError 175 } 176 177 func (e ErrEndpointNotFound) Error() string { 178 e.DefaultErrString = "No suitable endpoint could be found in the service catalog." 179 return e.choseErrString() 180 } 181 182 // ErrResourceNotFound is the error when trying to retrieve a resource's 183 // ID by name and the resource doesn't exist. 184 type ErrResourceNotFound struct { 185 BaseError 186 Name string 187 ResourceType string 188 } 189 190 func (e ErrResourceNotFound) Error() string { 191 e.DefaultErrString = fmt.Sprintf("Unable to find %s with name %s", e.ResourceType, e.Name) 192 return e.choseErrString() 193 } 194 195 // ErrMultipleResourcesFound is the error when trying to retrieve a resource's 196 // ID by name and multiple resources have the user-provided name. 197 type ErrMultipleResourcesFound struct { 198 BaseError 199 Name string 200 Count int 201 ResourceType string 202 } 203 204 func (e ErrMultipleResourcesFound) Error() string { 205 e.DefaultErrString = fmt.Sprintf("Found %d %ss matching %s", e.Count, e.ResourceType, e.Name) 206 return e.choseErrString() 207 } 208 209 // ErrUnexpectedType is the error when an unexpected type is encountered 210 type ErrUnexpectedType struct { 211 BaseError 212 Expected string 213 Actual string 214 } 215 216 func (e ErrUnexpectedType) Error() string { 217 e.DefaultErrString = fmt.Sprintf("Expected %s but got %s", e.Expected, e.Actual) 218 return e.choseErrString() 219 } 220 221 func unacceptedAttributeErr(attribute string) string { 222 return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute) 223 } 224 225 func redundantWithTokenErr(attribute string) string { 226 return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute) 227 } 228 229 func redundantWithUserID(attribute string) string { 230 return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute) 231 } 232 233 // ErrAPIKeyProvided indicates that an APIKey was provided but can't be used. 234 type ErrAPIKeyProvided struct{ BaseError } 235 236 func (e ErrAPIKeyProvided) Error() string { 237 return unacceptedAttributeErr("APIKey") 238 } 239 240 // ErrTenantIDProvided indicates that a TenantID was provided but can't be used. 241 type ErrTenantIDProvided struct{ BaseError } 242 243 func (e ErrTenantIDProvided) Error() string { 244 return unacceptedAttributeErr("TenantID") 245 } 246 247 // ErrTenantNameProvided indicates that a TenantName was provided but can't be used. 248 type ErrTenantNameProvided struct{ BaseError } 249 250 func (e ErrTenantNameProvided) Error() string { 251 return unacceptedAttributeErr("TenantName") 252 } 253 254 // ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead. 255 type ErrUsernameWithToken struct{ BaseError } 256 257 func (e ErrUsernameWithToken) Error() string { 258 return redundantWithTokenErr("Username") 259 } 260 261 // ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead. 262 type ErrUserIDWithToken struct{ BaseError } 263 264 func (e ErrUserIDWithToken) Error() string { 265 return redundantWithTokenErr("UserID") 266 } 267 268 // ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead. 269 type ErrDomainIDWithToken struct{ BaseError } 270 271 func (e ErrDomainIDWithToken) Error() string { 272 return redundantWithTokenErr("DomainID") 273 } 274 275 // ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s 276 type ErrDomainNameWithToken struct{ BaseError } 277 278 func (e ErrDomainNameWithToken) Error() string { 279 return redundantWithTokenErr("DomainName") 280 } 281 282 // ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once. 283 type ErrUsernameOrUserID struct{ BaseError } 284 285 func (e ErrUsernameOrUserID) Error() string { 286 return "Exactly one of Username and UserID must be provided for password authentication" 287 } 288 289 // ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used. 290 type ErrDomainIDWithUserID struct{ BaseError } 291 292 func (e ErrDomainIDWithUserID) Error() string { 293 return redundantWithUserID("DomainID") 294 } 295 296 // ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used. 297 type ErrDomainNameWithUserID struct{ BaseError } 298 299 func (e ErrDomainNameWithUserID) Error() string { 300 return redundantWithUserID("DomainName") 301 } 302 303 // ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it. 304 // It may also indicate that both a DomainID and a DomainName were provided at once. 305 type ErrDomainIDOrDomainName struct{ BaseError } 306 307 func (e ErrDomainIDOrDomainName) Error() string { 308 return "You must provide exactly one of DomainID or DomainName to authenticate by Username" 309 } 310 311 // ErrMissingPassword indicates that no password was provided and no token is available. 312 type ErrMissingPassword struct{ BaseError } 313 314 func (e ErrMissingPassword) Error() string { 315 return "You must provide a password to authenticate" 316 } 317 318 // ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present. 319 type ErrScopeDomainIDOrDomainName struct{ BaseError } 320 321 func (e ErrScopeDomainIDOrDomainName) Error() string { 322 return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName" 323 } 324 325 // ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope. 326 type ErrScopeProjectIDOrProjectName struct{ BaseError } 327 328 func (e ErrScopeProjectIDOrProjectName) Error() string { 329 return "You must provide at most one of ProjectID or ProjectName in a Scope" 330 } 331 332 // ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope. 333 type ErrScopeProjectIDAlone struct{ BaseError } 334 335 func (e ErrScopeProjectIDAlone) Error() string { 336 return "ProjectID must be supplied alone in a Scope" 337 } 338 339 // ErrScopeEmpty indicates that no credentials were provided in a Scope. 340 type ErrScopeEmpty struct{ BaseError } 341 342 func (e ErrScopeEmpty) Error() string { 343 return "You must provide either a Project or Domain in a Scope" 344 } 345 346 // ErrAppCredMissingSecret indicates that no Application Credential Secret was provided with Application Credential ID or Name 347 type ErrAppCredMissingSecret struct{ BaseError } 348 349 func (e ErrAppCredMissingSecret) Error() string { 350 return "You must provide an Application Credential Secret" 351 }