aws-sdk-core 3.46.2 → 3.126.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1258 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -1
  5. data/lib/aws-defaults/default_configuration.rb +153 -0
  6. data/lib/aws-defaults/defaults_mode_config_resolver.rb +107 -0
  7. data/lib/aws-defaults.rb +3 -0
  8. data/lib/aws-sdk-core/arn.rb +92 -0
  9. data/lib/aws-sdk-core/arn_parser.rb +40 -0
  10. data/lib/aws-sdk-core/assume_role_credentials.rb +20 -0
  11. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +109 -0
  12. data/lib/aws-sdk-core/async_client_stubs.rb +82 -0
  13. data/lib/aws-sdk-core/binary/decode_handler.rb +11 -1
  14. data/lib/aws-sdk-core/binary/encode_handler.rb +34 -0
  15. data/lib/aws-sdk-core/binary/event_builder.rb +124 -0
  16. data/lib/aws-sdk-core/binary/event_parser.rb +50 -18
  17. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +7 -2
  18. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +55 -0
  19. data/lib/aws-sdk-core/binary.rb +5 -0
  20. data/lib/aws-sdk-core/client_side_monitoring/publisher.rb +11 -1
  21. data/lib/aws-sdk-core/client_side_monitoring/request_metrics.rb +2 -0
  22. data/lib/aws-sdk-core/client_stubs.rb +16 -13
  23. data/lib/aws-sdk-core/credential_provider.rb +1 -30
  24. data/lib/aws-sdk-core/credential_provider_chain.rb +102 -40
  25. data/lib/aws-sdk-core/credentials.rb +2 -0
  26. data/lib/aws-sdk-core/deprecations.rb +17 -11
  27. data/lib/aws-sdk-core/eager_loader.rb +2 -0
  28. data/lib/aws-sdk-core/ec2_metadata.rb +238 -0
  29. data/lib/aws-sdk-core/ecs_credentials.rb +18 -9
  30. data/lib/aws-sdk-core/endpoint_cache.rb +16 -11
  31. data/lib/aws-sdk-core/errors.rb +138 -15
  32. data/lib/aws-sdk-core/event_emitter.rb +44 -0
  33. data/lib/aws-sdk-core/ini_parser.rb +2 -0
  34. data/lib/aws-sdk-core/instance_profile_credentials.rb +179 -42
  35. data/lib/aws-sdk-core/json/builder.rb +2 -0
  36. data/lib/aws-sdk-core/json/error_handler.rb +21 -2
  37. data/lib/aws-sdk-core/json/handler.rb +21 -1
  38. data/lib/aws-sdk-core/json/json_engine.rb +12 -8
  39. data/lib/aws-sdk-core/json/oj_engine.rb +35 -6
  40. data/lib/aws-sdk-core/json/parser.rb +10 -0
  41. data/lib/aws-sdk-core/json.rb +11 -28
  42. data/lib/aws-sdk-core/log/formatter.rb +16 -4
  43. data/lib/aws-sdk-core/log/handler.rb +2 -0
  44. data/lib/aws-sdk-core/log/param_filter.rb +38 -13
  45. data/lib/aws-sdk-core/log/param_formatter.rb +2 -0
  46. data/lib/aws-sdk-core/pageable_response.rb +48 -24
  47. data/lib/aws-sdk-core/pager.rb +5 -0
  48. data/lib/aws-sdk-core/param_converter.rb +2 -0
  49. data/lib/aws-sdk-core/param_validator.rb +63 -7
  50. data/lib/aws-sdk-core/plugins/api_key.rb +5 -1
  51. data/lib/aws-sdk-core/plugins/apig_authorizer_token.rb +2 -0
  52. data/lib/aws-sdk-core/plugins/apig_credentials_configuration.rb +2 -0
  53. data/lib/aws-sdk-core/plugins/apig_user_agent.rb +2 -0
  54. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +28 -1
  55. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +2 -0
  56. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +26 -7
  57. data/lib/aws-sdk-core/plugins/defaults_mode.rb +40 -0
  58. data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +12 -4
  59. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +8 -6
  60. data/lib/aws-sdk-core/plugins/event_stream_configuration.rb +16 -0
  61. data/lib/aws-sdk-core/plugins/global_configuration.rb +2 -0
  62. data/lib/aws-sdk-core/plugins/helpful_socket_errors.rb +2 -0
  63. data/lib/aws-sdk-core/plugins/http_checksum.rb +57 -0
  64. data/lib/aws-sdk-core/plugins/idempotency_token.rb +2 -0
  65. data/lib/aws-sdk-core/plugins/invocation_id.rb +35 -0
  66. data/lib/aws-sdk-core/plugins/jsonvalue_converter.rb +2 -0
  67. data/lib/aws-sdk-core/plugins/logging.rb +2 -0
  68. data/lib/aws-sdk-core/plugins/param_converter.rb +2 -0
  69. data/lib/aws-sdk-core/plugins/param_validator.rb +2 -0
  70. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +19 -0
  71. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -0
  72. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +2 -0
  73. data/lib/aws-sdk-core/plugins/protocols/query.rb +2 -0
  74. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +18 -1
  75. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +2 -0
  76. data/lib/aws-sdk-core/plugins/recursion_detection.rb +27 -0
  77. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -16
  78. data/lib/aws-sdk-core/plugins/response_paging.rb +2 -0
  79. data/lib/aws-sdk-core/plugins/retries/client_rate_limiter.rb +139 -0
  80. data/lib/aws-sdk-core/plugins/retries/clock_skew.rb +100 -0
  81. data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +146 -0
  82. data/lib/aws-sdk-core/plugins/retries/retry_quota.rb +59 -0
  83. data/lib/aws-sdk-core/plugins/retry_errors.rb +295 -107
  84. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -0
  85. data/lib/aws-sdk-core/plugins/signature_v4.rb +28 -25
  86. data/lib/aws-sdk-core/plugins/stub_responses.rb +24 -7
  87. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +53 -0
  88. data/lib/aws-sdk-core/plugins/user_agent.rb +6 -8
  89. data/lib/aws-sdk-core/process_credentials.rb +12 -5
  90. data/lib/aws-sdk-core/query/ec2_param_builder.rb +2 -0
  91. data/lib/aws-sdk-core/query/handler.rb +2 -0
  92. data/lib/aws-sdk-core/query/param.rb +2 -0
  93. data/lib/aws-sdk-core/query/param_builder.rb +2 -0
  94. data/lib/aws-sdk-core/query/param_list.rb +2 -0
  95. data/lib/aws-sdk-core/query.rb +2 -0
  96. data/lib/aws-sdk-core/refreshing_credentials.rb +15 -2
  97. data/lib/aws-sdk-core/resources/collection.rb +2 -0
  98. data/lib/aws-sdk-core/rest/handler.rb +2 -0
  99. data/lib/aws-sdk-core/rest/request/body.rb +21 -1
  100. data/lib/aws-sdk-core/rest/request/builder.rb +2 -0
  101. data/lib/aws-sdk-core/rest/request/endpoint.rb +10 -3
  102. data/lib/aws-sdk-core/rest/request/headers.rb +20 -6
  103. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +4 -2
  104. data/lib/aws-sdk-core/rest/response/body.rb +2 -0
  105. data/lib/aws-sdk-core/rest/response/headers.rb +6 -3
  106. data/lib/aws-sdk-core/rest/response/parser.rb +2 -0
  107. data/lib/aws-sdk-core/rest/response/status_code.rb +2 -0
  108. data/lib/aws-sdk-core/rest.rb +2 -0
  109. data/lib/aws-sdk-core/shared_config.rb +153 -127
  110. data/lib/aws-sdk-core/shared_credentials.rb +9 -1
  111. data/lib/aws-sdk-core/sso_credentials.rb +136 -0
  112. data/lib/aws-sdk-core/structure.rb +14 -4
  113. data/lib/aws-sdk-core/stubbing/data_applicator.rb +2 -0
  114. data/lib/aws-sdk-core/stubbing/empty_stub.rb +2 -0
  115. data/lib/aws-sdk-core/stubbing/protocols/api_gateway.rb +2 -0
  116. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +2 -0
  117. data/lib/aws-sdk-core/stubbing/protocols/json.rb +3 -1
  118. data/lib/aws-sdk-core/stubbing/protocols/query.rb +4 -2
  119. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +52 -7
  120. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +3 -1
  121. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +2 -2
  122. data/lib/aws-sdk-core/stubbing/stub_data.rb +15 -4
  123. data/lib/aws-sdk-core/stubbing/xml_error.rb +2 -0
  124. data/lib/aws-sdk-core/type_builder.rb +2 -0
  125. data/lib/aws-sdk-core/util.rb +6 -0
  126. data/lib/aws-sdk-core/waiters/errors.rb +2 -0
  127. data/lib/aws-sdk-core/waiters/poller.rb +2 -0
  128. data/lib/aws-sdk-core/waiters/waiter.rb +4 -2
  129. data/lib/aws-sdk-core/waiters.rb +2 -0
  130. data/lib/aws-sdk-core/xml/builder.rb +5 -3
  131. data/lib/aws-sdk-core/xml/default_list.rb +2 -0
  132. data/lib/aws-sdk-core/xml/default_map.rb +2 -0
  133. data/lib/aws-sdk-core/xml/doc_builder.rb +15 -4
  134. data/lib/aws-sdk-core/xml/error_handler.rb +29 -4
  135. data/lib/aws-sdk-core/xml/parser/engines/libxml.rb +2 -0
  136. data/lib/aws-sdk-core/xml/parser/engines/nokogiri.rb +2 -0
  137. data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
  138. data/lib/aws-sdk-core/xml/parser/engines/ox.rb +3 -1
  139. data/lib/aws-sdk-core/xml/parser/engines/rexml.rb +4 -1
  140. data/lib/aws-sdk-core/xml/parser/frame.rb +25 -0
  141. data/lib/aws-sdk-core/xml/parser/parsing_error.rb +2 -0
  142. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  143. data/lib/aws-sdk-core/xml/parser.rb +7 -0
  144. data/lib/aws-sdk-core/xml.rb +2 -0
  145. data/lib/aws-sdk-core.rb +23 -4
  146. data/lib/aws-sdk-sso/client.rb +568 -0
  147. data/lib/aws-sdk-sso/client_api.rb +190 -0
  148. data/lib/aws-sdk-sso/customizations.rb +1 -0
  149. data/lib/aws-sdk-sso/errors.rb +102 -0
  150. data/lib/aws-sdk-sso/resource.rb +26 -0
  151. data/lib/aws-sdk-sso/types.rb +352 -0
  152. data/lib/aws-sdk-sso.rb +55 -0
  153. data/lib/aws-sdk-sts/client.rb +1282 -531
  154. data/lib/aws-sdk-sts/client_api.rb +76 -1
  155. data/lib/aws-sdk-sts/customizations.rb +4 -0
  156. data/lib/aws-sdk-sts/errors.rb +153 -1
  157. data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +38 -0
  158. data/lib/aws-sdk-sts/presigner.rb +75 -0
  159. data/lib/aws-sdk-sts/resource.rb +4 -1
  160. data/lib/aws-sdk-sts/types.rb +958 -229
  161. data/lib/aws-sdk-sts.rb +16 -6
  162. data/lib/seahorse/client/async_base.rb +52 -0
  163. data/lib/seahorse/client/async_response.rb +64 -0
  164. data/lib/seahorse/client/base.rb +7 -2
  165. data/lib/seahorse/client/block_io.rb +6 -2
  166. data/lib/seahorse/client/configuration.rb +7 -1
  167. data/lib/seahorse/client/events.rb +3 -1
  168. data/lib/seahorse/client/h2/connection.rb +250 -0
  169. data/lib/seahorse/client/h2/handler.rb +152 -0
  170. data/lib/seahorse/client/handler.rb +2 -0
  171. data/lib/seahorse/client/handler_builder.rb +2 -0
  172. data/lib/seahorse/client/handler_list.rb +2 -0
  173. data/lib/seahorse/client/handler_list_entry.rb +6 -4
  174. data/lib/seahorse/client/http/async_response.rb +44 -0
  175. data/lib/seahorse/client/http/headers.rb +2 -0
  176. data/lib/seahorse/client/http/request.rb +5 -3
  177. data/lib/seahorse/client/http/response.rb +18 -11
  178. data/lib/seahorse/client/logging/formatter.rb +6 -2
  179. data/lib/seahorse/client/logging/handler.rb +2 -0
  180. data/lib/seahorse/client/managed_file.rb +2 -0
  181. data/lib/seahorse/client/net_http/connection_pool.rb +30 -23
  182. data/lib/seahorse/client/net_http/handler.rb +24 -7
  183. data/lib/seahorse/client/net_http/patches.rb +15 -84
  184. data/lib/seahorse/client/networking_error.rb +30 -0
  185. data/lib/seahorse/client/plugin.rb +10 -7
  186. data/lib/seahorse/client/plugin_list.rb +2 -0
  187. data/lib/seahorse/client/plugins/content_length.rb +14 -3
  188. data/lib/seahorse/client/plugins/endpoint.rb +4 -2
  189. data/lib/seahorse/client/plugins/h2.rb +69 -0
  190. data/lib/seahorse/client/plugins/logging.rb +2 -0
  191. data/lib/seahorse/client/plugins/net_http.rb +39 -3
  192. data/lib/seahorse/client/plugins/operation_methods.rb +2 -0
  193. data/lib/seahorse/client/plugins/raise_response_errors.rb +2 -0
  194. data/lib/seahorse/client/plugins/request_callback.rb +110 -0
  195. data/lib/seahorse/client/plugins/response_target.rb +23 -14
  196. data/lib/seahorse/client/request.rb +2 -0
  197. data/lib/seahorse/client/request_context.rb +2 -0
  198. data/lib/seahorse/client/response.rb +5 -5
  199. data/lib/seahorse/model/api.rb +10 -0
  200. data/lib/seahorse/model/authorizer.rb +2 -0
  201. data/lib/seahorse/model/operation.rb +9 -0
  202. data/lib/seahorse/model/shapes.rb +29 -2
  203. data/lib/seahorse/util.rb +8 -1
  204. data/lib/seahorse/version.rb +2 -0
  205. data/lib/seahorse.rb +12 -0
  206. metadata +64 -14
@@ -1,13 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
4
+ require_relative 'retries/error_inspector'
5
+ require_relative 'retries/retry_quota'
6
+ require_relative 'retries/client_rate_limiter'
7
+ require_relative 'retries/clock_skew'
2
8
 
3
9
  module Aws
4
10
  module Plugins
5
11
  # @api private
6
12
  class RetryErrors < Seahorse::Client::Plugin
7
-
8
- EQUAL_JITTER = lambda { |delay| (delay / 2) + Kernel.rand(0..(delay/2))}
9
- FULL_JITTER= lambda { |delay| Kernel.rand(0..delay) }
10
- NO_JITTER = lambda { |delay| delay }
13
+ # BEGIN LEGACY OPTIONS
14
+ EQUAL_JITTER = ->(delay) { (delay / 2) + Kernel.rand(0..(delay / 2)) }
15
+ FULL_JITTER = ->(delay) { Kernel.rand(0..delay) }
16
+ NO_JITTER = ->(delay) { delay }
11
17
 
12
18
  JITTERS = {
13
19
  none: NO_JITTER,
@@ -15,163 +21,349 @@ module Aws
15
21
  full: FULL_JITTER
16
22
  }
17
23
 
18
- JITTERS.default_proc = lambda { |h,k|
19
- raise KeyError, "#{k} is not a named jitter function. Must be one of #{h.keys}"
24
+ JITTERS.default_proc = lambda { |h, k|
25
+ raise KeyError,
26
+ "#{k} is not a named jitter function. Must be one of #{h.keys}"
20
27
  }
21
28
 
22
29
  DEFAULT_BACKOFF = lambda do |c|
23
- delay = 2 ** c.retries * c.config.retry_base_delay
24
- delay = [delay, c.config.retry_max_delay].min if (c.config.retry_max_delay || 0) > 0
30
+ delay = 2**c.retries * c.config.retry_base_delay
31
+ if (c.config.retry_max_delay || 0) > 0
32
+ delay = [delay, c.config.retry_max_delay].min
33
+ end
25
34
  jitter = c.config.retry_jitter
26
- jitter = JITTERS[jitter] if Symbol === jitter
35
+ jitter = JITTERS[jitter] if jitter.is_a?(Symbol)
27
36
  delay = jitter.call(delay) if jitter
28
37
  Kernel.sleep(delay)
29
38
  end
30
39
 
31
- option(:retry_limit,
40
+ option(
41
+ :retry_limit,
32
42
  default: 3,
33
43
  doc_type: Integer,
34
44
  docstring: <<-DOCS)
35
45
  The maximum number of times to retry failed requests. Only
36
46
  ~ 500 level server errors and certain ~ 400 level client errors
37
47
  are retried. Generally, these are throttling errors, data
38
- checksum errors, networking errors, timeout errors and auth
39
- errors from expired credentials.
48
+ checksum errors, networking errors, timeout errors, auth errors,
49
+ endpoint discovery, and errors from expired credentials.
50
+ This option is only used in the `legacy` retry mode.
40
51
  DOCS
41
52
 
42
- option(:retry_max_delay,
53
+ option(
54
+ :retry_max_delay,
43
55
  default: 0,
44
56
  doc_type: Integer,
45
57
  docstring: <<-DOCS)
46
- The maximum number of seconds to delay between retries (0 for no limit) used by the default backoff function.
58
+ The maximum number of seconds to delay between retries (0 for no limit)
59
+ used by the default backoff function. This option is only used in the
60
+ `legacy` retry mode.
47
61
  DOCS
48
62
 
49
- option(:retry_base_delay,
63
+ option(
64
+ :retry_base_delay,
50
65
  default: 0.3,
51
66
  doc_type: Float,
52
67
  docstring: <<-DOCS)
53
- The base delay in seconds used by the default backoff function.
68
+ The base delay in seconds used by the default backoff function. This option
69
+ is only used in the `legacy` retry mode.
54
70
  DOCS
55
71
 
56
- option(:retry_jitter,
72
+ option(
73
+ :retry_jitter,
57
74
  default: :none,
58
75
  doc_type: Symbol,
59
76
  docstring: <<-DOCS)
60
- A delay randomiser function used by the default backoff function. Some predefined functions can be referenced by name - :none, :equal, :full, otherwise a Proc that takes and returns a number.
77
+ A delay randomiser function used by the default backoff function.
78
+ Some predefined functions can be referenced by name - :none, :equal, :full,
79
+ otherwise a Proc that takes and returns a number. This option is only used
80
+ in the `legacy` retry mode.
61
81
 
62
82
  @see https://www.awsarchitectureblog.com/2015/03/backoff.html
63
83
  DOCS
64
84
 
65
- option(:retry_backoff, DEFAULT_BACKOFF)
85
+ option(
86
+ :retry_backoff,
87
+ default: DEFAULT_BACKOFF,
88
+ doc_type: Proc,
89
+ docstring: <<-DOCS)
90
+ A proc or lambda used for backoff. Defaults to 2**retries * retry_base_delay.
91
+ This option is only used in the `legacy` retry mode.
92
+ DOCS
66
93
 
67
- # @api private
68
- class ErrorInspector
94
+ # END LEGACY OPTIONS
69
95
 
70
- EXPIRED_CREDS = Set.new([
71
- 'InvalidClientTokenId', # query services
72
- 'UnrecognizedClientException', # json services
73
- 'InvalidAccessKeyId', # s3
74
- 'AuthFailure', # ec2
75
- ])
96
+ option(
97
+ :retry_mode,
98
+ default: 'legacy',
99
+ doc_type: String,
100
+ docstring: <<-DOCS) do |cfg|
101
+ Specifies which retry algorithm to use. Values are:
76
102
 
77
- THROTTLING_ERRORS = Set.new([
78
- 'Throttling', # query services
79
- 'ThrottlingException', # json services
80
- 'RequestThrottled', # sqs
81
- 'RequestThrottledException',
82
- 'ProvisionedThroughputExceededException', # dynamodb
83
- 'TransactionInProgressException', # dynamodb
84
- 'RequestLimitExceeded', # ec2
85
- 'BandwidthLimitExceeded', # cloud search
86
- 'LimitExceededException', # kinesis
87
- 'TooManyRequestsException', # batch
88
- ])
103
+ * `legacy` - The pre-existing retry behavior. This is default value if
104
+ no retry mode is provided.
89
105
 
90
- CHECKSUM_ERRORS = Set.new([
91
- 'CRC32CheckFailed', # dynamodb
92
- ])
106
+ * `standard` - A standardized set of retry rules across the AWS SDKs.
107
+ This includes support for retry quotas, which limit the number of
108
+ unsuccessful retries a client can make.
93
109
 
94
- NETWORKING_ERRORS = Set.new([
95
- 'RequestTimeout', # s3
96
- ])
110
+ * `adaptive` - An experimental retry mode that includes all the
111
+ functionality of `standard` mode along with automatic client side
112
+ throttling. This is a provisional mode that may change behavior
113
+ in the future.
97
114
 
98
- def initialize(error, http_status_code)
99
- @error = error
100
- @name = extract_name(error)
101
- @http_status_code = http_status_code
102
- end
115
+ DOCS
116
+ resolve_retry_mode(cfg)
117
+ end
118
+
119
+ option(
120
+ :max_attempts,
121
+ default: 3,
122
+ doc_type: Integer,
123
+ docstring: <<-DOCS) do |cfg|
124
+ An integer representing the maximum number attempts that will be made for
125
+ a single request, including the initial attempt. For example,
126
+ setting this value to 5 will result in a request being retried up to
127
+ 4 times. Used in `standard` and `adaptive` retry modes.
128
+ DOCS
129
+ resolve_max_attempts(cfg)
130
+ end
131
+
132
+ option(
133
+ :adaptive_retry_wait_to_fill,
134
+ default: true,
135
+ doc_type: 'Boolean',
136
+ docstring: <<-DOCS) do |cfg|
137
+ Used only in `adaptive` retry mode. When true, the request will sleep
138
+ until there is sufficent client side capacity to retry the request.
139
+ When false, the request will raise a `RetryCapacityNotAvailableError` and will
140
+ not retry instead of sleeping.
141
+ DOCS
142
+ resolve_adaptive_retry_wait_to_fill(cfg)
143
+ end
144
+
145
+ option(
146
+ :correct_clock_skew,
147
+ default: true,
148
+ doc_type: 'Boolean',
149
+ docstring: <<-DOCS) do |cfg|
150
+ Used only in `standard` and adaptive retry modes. Specifies whether to apply
151
+ a clock skew correction and retry requests with skewed client clocks.
152
+ DOCS
153
+ resolve_correct_clock_skew(cfg)
154
+ end
103
155
 
104
- def expired_credentials?
105
- !!(EXPIRED_CREDS.include?(@name) || @name.match(/expired/i))
156
+ # @api private undocumented
157
+ option(:client_rate_limiter) { Retries::ClientRateLimiter.new }
158
+
159
+ # @api private undocumented
160
+ option(:retry_quota) { Retries::RetryQuota.new }
161
+
162
+ # @api private undocumented
163
+ option(:clock_skew) { Retries::ClockSkew.new }
164
+
165
+ def self.resolve_retry_mode(cfg)
166
+ default_mode_value =
167
+ if cfg.respond_to?(:defaults_mode_config_resolver)
168
+ cfg.defaults_mode_config_resolver.resolve(:retry_mode)
169
+ end
170
+
171
+ value = ENV['AWS_RETRY_MODE'] ||
172
+ Aws.shared_config.retry_mode(profile: cfg.profile) ||
173
+ default_mode_value ||
174
+ 'legacy'
175
+ # Raise if provided value is not one of the retry modes
176
+ if value != 'legacy' && value != 'standard' && value != 'adaptive'
177
+ raise ArgumentError,
178
+ 'Must provide either `legacy`, `standard`, or `adaptive` for '\
179
+ 'retry_mode profile option or for ENV[\'AWS_RETRY_MODE\']'
106
180
  end
181
+ value
182
+ end
107
183
 
108
- def throttling_error?
109
- !!(THROTTLING_ERRORS.include?(@name) || @name.match(/throttl/i) || @http_status_code == 429)
184
+ def self.resolve_max_attempts(cfg)
185
+ value = (ENV['AWS_MAX_ATTEMPTS']) ||
186
+ Aws.shared_config.max_attempts(profile: cfg.profile) ||
187
+ '3'
188
+ value = value.to_i
189
+ # Raise if provided value is not a positive integer
190
+ if value <= 0
191
+ raise ArgumentError,
192
+ 'Must provide a positive integer for max_attempts profile '\
193
+ 'option or for ENV[\'AWS_MAX_ATTEMPTS\']'
110
194
  end
195
+ value
196
+ end
111
197
 
112
- def checksum?
113
- CHECKSUM_ERRORS.include?(@name) || @error.is_a?(Errors::ChecksumError)
198
+ def self.resolve_adaptive_retry_wait_to_fill(cfg)
199
+ value = ENV['AWS_ADAPTIVE_RETRY_WAIT_TO_FILL'] ||
200
+ Aws.shared_config.adaptive_retry_wait_to_fill(profile: cfg.profile) ||
201
+ 'true'
202
+ # Raise if provided value is not true or false
203
+ if value != 'true' && value != 'false'
204
+ raise ArgumentError,
205
+ 'Must provide either `true` or `false` for '\
206
+ 'adaptive_retry_wait_to_fill profile option or for '\
207
+ 'ENV[\'AWS_ADAPTIVE_RETRY_WAIT_TO_FILL\']'
114
208
  end
209
+ value == 'true'
210
+ end
115
211
 
116
- def networking?
117
- @error.is_a?(Seahorse::Client::NetworkingError) ||
118
- NETWORKING_ERRORS.include?(@name)
212
+ def self.resolve_correct_clock_skew(cfg)
213
+ value = ENV['AWS_CORRECT_CLOCK_SKEW'] ||
214
+ Aws.shared_config.correct_clock_skew(profile: cfg.profile) ||
215
+ 'true'
216
+ # Raise if provided value is not true or false
217
+ if value != 'true' && value != 'false'
218
+ raise ArgumentError,
219
+ 'Must provide either `true` or `false` for '\
220
+ 'correct_clock_skew profile option or for '\
221
+ 'ENV[\'AWS_CORRECT_CLOCK_SKEW\']'
119
222
  end
223
+ value == 'true'
224
+ end
225
+
226
+ class Handler < Seahorse::Client::Handler
227
+ # Max backoff (in seconds)
228
+ MAX_BACKOFF = 20
229
+
230
+ def call(context)
231
+ context.metadata[:retries] ||= {}
232
+ config = context.config
233
+
234
+ get_send_token(config)
235
+ add_retry_headers(context)
236
+ response = @handler.call(context)
237
+ error_inspector = Retries::ErrorInspector.new(
238
+ response.error, response.context.http_response.status_code
239
+ )
240
+
241
+ request_bookkeeping(context, response, error_inspector)
242
+
243
+ if error_inspector.endpoint_discovery?(context)
244
+ key = config.endpoint_cache.extract_key(context)
245
+ config.endpoint_cache.delete(key)
246
+ end
120
247
 
121
- def server?
122
- (500..599).include?(@http_status_code)
248
+ # Clock correction needs to be updated from the response even when
249
+ # the request is not retryable but should only be updated
250
+ # in the case of clock skew errors
251
+ if error_inspector.clock_skew?(context)
252
+ config.clock_skew.update_clock_correction(context)
253
+ end
254
+
255
+ # Estimated skew needs to be updated on every request
256
+ config.clock_skew.update_estimated_skew(context)
257
+
258
+ return response unless retryable?(context, response, error_inspector)
259
+
260
+ return response if context.retries >= config.max_attempts - 1
261
+
262
+ context.metadata[:retries][:capacity_amount] =
263
+ config.retry_quota.checkout_capacity(error_inspector)
264
+ return response unless context.metadata[:retries][:capacity_amount] > 0
265
+
266
+ delay = exponential_backoff(context.retries)
267
+ Kernel.sleep(delay)
268
+ retry_request(context, error_inspector)
123
269
  end
124
270
 
125
- def endpoint_discovery?(context)
126
- return false unless context.operation.endpoint_discovery
271
+ private
127
272
 
128
- if @http_status_code == 421 ||
129
- extract_name(@error) == 'InvalidEndpointException'
130
- @error = Errors::EndpointDiscoveryError.new
273
+ def get_send_token(config)
274
+ # either fail fast or block until a token becomes available
275
+ # must be configurable
276
+ # need a maximum rate at which we can send requests (max_send_rate)
277
+ # is unset until a throttle is seen
278
+ if config.retry_mode == 'adaptive'
279
+ config.client_rate_limiter.token_bucket_acquire(
280
+ 1,
281
+ config.adaptive_retry_wait_to_fill
282
+ )
131
283
  end
284
+ end
132
285
 
133
- # When endpoint discovery error occurs
134
- # evict the endpoint from cache
135
- if @error.is_a?(Errors::EndpointDiscoveryError)
136
- key = context.config.endpoint_cache.extract_key(context)
137
- context.config.endpoint_cache.delete(key)
138
- true
139
- else
140
- false
286
+ # maxsendrate is updated if on adaptive mode and based on response
287
+ # retry quota is updated if the request is successful (both modes)
288
+ def request_bookkeeping(context, response, error_inspector)
289
+ config = context.config
290
+ if response.successful?
291
+ config.retry_quota.release(
292
+ context.metadata[:retries][:capacity_amount]
293
+ )
294
+ end
295
+
296
+ if config.retry_mode == 'adaptive'
297
+ is_throttling_error = error_inspector.throttling_error?
298
+ config.client_rate_limiter.update_sending_rate(is_throttling_error)
141
299
  end
142
300
  end
143
-
144
- def retryable?(context)
145
- (expired_credentials? and refreshable_credentials?(context)) or
146
- throttling_error? or
147
- checksum? or
148
- networking? or
149
- server? or
150
- endpoint_discovery?(context)
301
+
302
+ def retryable?(context, response, error_inspector)
303
+ return false if response.successful?
304
+
305
+ error_inspector.retryable?(context) &&
306
+ context.http_response.body.respond_to?(:truncate)
151
307
  end
152
308
 
153
- private
309
+ def exponential_backoff(retries)
310
+ # for a transient error, use backoff
311
+ [Kernel.rand * 2**retries, MAX_BACKOFF].min
312
+ end
154
313
 
155
- def refreshable_credentials?(context)
156
- context.config.credentials.respond_to?(:refresh!)
314
+ def retry_request(context, error)
315
+ context.retries += 1
316
+ context.config.credentials.refresh! if error.expired_credentials?
317
+ context.http_request.body.rewind
318
+ context.http_response.reset
319
+ call(context)
157
320
  end
158
321
 
159
- def extract_name(error)
160
- if error.is_a?(Errors::ServiceError)
161
- error.class.code
162
- else
163
- error.class.name.to_s
322
+ def add_retry_headers(context)
323
+ request_pairs = {
324
+ 'attempt' => context.retries,
325
+ 'max' => context.config.max_attempts
326
+ }
327
+ if (ttl = compute_request_ttl(context))
328
+ request_pairs['ttl'] = ttl
164
329
  end
330
+
331
+ # create the request header
332
+ formatted_header = request_pairs.map { |k, v| "#{k}=#{v}" }.join('; ')
333
+ context.http_request.headers['amz-sdk-request'] = formatted_header
165
334
  end
166
335
 
336
+ def compute_request_ttl(context)
337
+ return if context.operation.async
338
+
339
+ endpoint = context.http_request.endpoint
340
+ estimated_skew = context.config.clock_skew.estimated_skew(endpoint)
341
+ if context.config.respond_to?(:http_read_timeout)
342
+ read_timeout = context.config.http_read_timeout
343
+ end
344
+
345
+ if estimated_skew && read_timeout
346
+ (Time.now.utc + read_timeout + estimated_skew)
347
+ .strftime('%Y%m%dT%H%M%SZ')
348
+ end
349
+ end
167
350
  end
168
351
 
169
- class Handler < Seahorse::Client::Handler
352
+ class LegacyHandler < Seahorse::Client::Handler
170
353
 
171
354
  def call(context)
172
355
  response = @handler.call(context)
173
356
  if response.error
174
- retry_if_possible(response)
357
+ error_inspector = Retries::ErrorInspector.new(
358
+ response.error, response.context.http_response.status_code
359
+ )
360
+
361
+ if error_inspector.endpoint_discovery?(context)
362
+ key = context.config.endpoint_cache.extract_key(context)
363
+ context.config.endpoint_cache.delete(key)
364
+ end
365
+
366
+ retry_if_possible(response, error_inspector)
175
367
  else
176
368
  response
177
369
  end
@@ -179,21 +371,15 @@ A delay randomiser function used by the default backoff function. Some predefine
179
371
 
180
372
  private
181
373
 
182
- def retry_if_possible(response)
374
+ def retry_if_possible(response, error_inspector)
183
375
  context = response.context
184
- error = error_for(response)
185
- if should_retry?(context, error)
186
- retry_request(context, error)
376
+ if should_retry?(context, error_inspector)
377
+ retry_request(context, error_inspector)
187
378
  else
188
379
  response
189
380
  end
190
381
  end
191
382
 
192
- def error_for(response)
193
- status_code = response.context.http_response.status_code
194
- ErrorInspector.new(response.error, status_code)
195
- end
196
-
197
383
  def retry_request(context, error)
198
384
  delay_retry(context)
199
385
  context.retries += 1
@@ -208,9 +394,9 @@ A delay randomiser function used by the default backoff function. Some predefine
208
394
  end
209
395
 
210
396
  def should_retry?(context, error)
211
- error.retryable?(context) and
212
- context.retries < retry_limit(context) and
213
- response_truncatable?(context)
397
+ error.retryable?(context) &&
398
+ context.retries < retry_limit(context) &&
399
+ response_truncatable?(context)
214
400
  end
215
401
 
216
402
  def retry_limit(context)
@@ -220,15 +406,17 @@ A delay randomiser function used by the default backoff function. Some predefine
220
406
  def response_truncatable?(context)
221
407
  context.http_response.body.respond_to?(:truncate)
222
408
  end
223
-
224
409
  end
225
410
 
226
411
  def add_handlers(handlers, config)
227
- if config.retry_limit > 0
412
+ if config.retry_mode == 'legacy'
413
+ if config.retry_limit > 0
414
+ handlers.add(LegacyHandler, step: :sign, priority: 99)
415
+ end
416
+ else
228
417
  handlers.add(Handler, step: :sign, priority: 99)
229
418
  end
230
419
  end
231
-
232
420
  end
233
421
  end
234
422
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module Plugins
3
5
  # @api private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aws-sigv4'
2
4
 
3
5
  module Aws
@@ -10,39 +12,29 @@ module Aws
10
12
  end
11
13
 
12
14
  option(:sigv4_name) do |cfg|
13
- cfg.api.metadata['signingName'] || cfg.api.metadata['endpointPrefix']
15
+ signingName = if cfg.region
16
+ Aws::Partitions::EndpointProvider.signing_service(
17
+ cfg.region, cfg.api.metadata['endpointPrefix']
18
+ )
19
+ end
20
+ signingName || cfg.api.metadata['signingName'] || cfg.api.metadata['endpointPrefix']
14
21
  end
15
22
 
16
23
  option(:sigv4_region) do |cfg|
17
-
18
- # The signature version 4 signing region is most
19
- # commonly the configured region. There are a few
20
- # notable exceptions:
21
- #
22
- # * Some services have a global endpoint to the entire
23
- # partition. For example, when constructing a route53
24
- # client for a region like "us-west-2", we will
25
- # always use "route53.amazonaws.com". This endpoint
26
- # is actually global to the entire partition,
27
- # and must be signed as "us-east-1".
28
- #
29
- # * When the region is configured, but it is configured
30
- # to a non region, such as "aws-global". This is similar
31
- # to the previous case. We use the Aws::Partitions::EndpointProvider
32
- # to resolve to the actual signing region.
33
- #
34
- prefix = cfg.api.metadata['endpointPrefix']
35
- if prefix && cfg.endpoint.to_s.match(/#{prefix}\.amazonaws\.com/)
36
- 'us-east-1'
37
- elsif cfg.region
38
- Aws::Partitions::EndpointProvider.signing_region(cfg.region, cfg.sigv4_name)
24
+ if cfg.region
25
+ if cfg.respond_to?(:sts_regional_endpoints)
26
+ sts_regional = cfg.sts_regional_endpoints
27
+ end
28
+ Aws::Partitions::EndpointProvider.signing_region(
29
+ cfg.region, cfg.api.metadata['endpointPrefix'], sts_regional
30
+ )
39
31
  end
40
32
  end
41
33
 
42
34
  option(:unsigned_operations) do |cfg|
43
35
  cfg.api.operation_names.inject([]) do |unsigned, operation_name|
44
36
  if cfg.api.operation(operation_name)['authtype'] == 'none' ||
45
- cfg.api.operation(operation_name)['authtype'] == 'custom'
37
+ cfg.api.operation(operation_name)['authtype'] == 'custom'
46
38
  # Unsign requests that has custom apigateway authorizer as well
47
39
  unsigned << operation_name
48
40
  else
@@ -107,6 +99,17 @@ module Aws
107
99
  req.headers.delete('X-Amz-Security-Token')
108
100
  req.headers.delete('X-Amz-Date')
109
101
 
102
+ if context.config.respond_to?(:clock_skew) &&
103
+ context.config.clock_skew &&
104
+ context.config.correct_clock_skew
105
+
106
+ endpoint = context.http_request.endpoint
107
+ skew = context.config.clock_skew.clock_correction(endpoint)
108
+ if skew.abs > 0
109
+ req.headers['X-Amz-Date'] = (Time.now.utc + skew).strftime("%Y%m%dT%H%M%SZ")
110
+ end
111
+ end
112
+
110
113
  # compute the signature
111
114
  begin
112
115
  signature = signer.sign_request(
@@ -130,7 +133,7 @@ module Aws
130
133
  # @api private
131
134
  def apply_authtype(context)
132
135
  if context.operation['authtype'].eql?('v4-unsigned-body') &&
133
- context.http_request.endpoint.scheme.eql?('https')
136
+ context.http_request.endpoint.scheme.eql?('https')
134
137
  context.http_request.headers['X-Amz-Content-Sha256'] = 'UNSIGNED-PAYLOAD'
135
138
  end
136
139
  context
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module Plugins
3
5
  # @api private
@@ -34,9 +36,12 @@ requests are made, and retries are disabled.
34
36
  if client.config.stub_responses
35
37
  client.setup_stubbing
36
38
  client.handlers.remove(RetryErrors::Handler)
39
+ client.handlers.remove(RetryErrors::LegacyHandler)
37
40
  client.handlers.remove(ClientMetricsPlugin::Handler)
38
41
  client.handlers.remove(ClientMetricsSendPlugin::LatencyHandler)
39
42
  client.handlers.remove(ClientMetricsSendPlugin::AttemptHandler)
43
+ client.handlers.remove(Seahorse::Client::Plugins::RequestCallback::OptionHandler)
44
+ client.handlers.remove(Seahorse::Client::Plugins::RequestCallback::ReadCallbackHandler)
40
45
  end
41
46
  end
42
47
 
@@ -45,15 +50,18 @@ requests are made, and retries are disabled.
45
50
  def call(context)
46
51
  stub = context.client.next_stub(context)
47
52
  resp = Seahorse::Client::Response.new(context: context)
48
- apply_stub(stub, resp)
49
- resp
53
+ async_mode = context.client.is_a? Seahorse::Client::AsyncBase
54
+ apply_stub(stub, resp, async_mode)
55
+
56
+ async_mode ? Seahorse::Client::AsyncResponse.new(
57
+ context: context, stream: context[:input_event_stream_handler].event_emitter.stream, sync_queue: Queue.new) : resp
50
58
  end
51
59
 
52
- def apply_stub(stub, response)
60
+ def apply_stub(stub, response, async_mode = false)
53
61
  http_resp = response.context.http_response
54
62
  case
55
63
  when stub[:error] then signal_error(stub[:error], http_resp)
56
- when stub[:http] then signal_http(stub[:http], http_resp)
64
+ when stub[:http] then signal_http(stub[:http], http_resp, async_mode)
57
65
  when stub[:data] then response.data = stub[:data]
58
66
  end
59
67
  end
@@ -67,9 +75,18 @@ requests are made, and retries are disabled.
67
75
  end
68
76
 
69
77
  # @param [Seahorse::Client::Http::Response] stub
70
- # @param [Seahorse::Client::Http::Response] http_resp
71
- def signal_http(stub, http_resp)
72
- http_resp.signal_headers(stub.status_code, stub.headers.to_h)
78
+ # @param [Seahorse::Client::Http::Response | Seahorse::Client::Http::AsyncResponse] http_resp
79
+ # @param [Boolean] async_mode
80
+ def signal_http(stub, http_resp, async_mode = false)
81
+ if async_mode
82
+ h2_headers = stub.headers.to_h.inject([]) do |arr, (k, v)|
83
+ arr << [k, v]
84
+ end
85
+ h2_headers << [":status", stub.status_code]
86
+ http_resp.signal_headers(h2_headers)
87
+ else
88
+ http_resp.signal_headers(stub.status_code, stub.headers.to_h)
89
+ end
73
90
  while chunk = stub.body.read(1024 * 1024)
74
91
  http_resp.signal_data(chunk)
75
92
  end