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  }