errors.go 14 KB

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