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  }