aws-sdk-core 2.11.175 → 2.11.176
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/apis/rekognition/2016-06-27/api-2.json +6 -1
- data/lib/aws-sdk-core.rb +7 -4
- data/lib/aws-sdk-core/api/builder.rb +24 -1
- data/lib/aws-sdk-core/api/customizations.rb +3 -1
- data/lib/aws-sdk-core/api/shape_map.rb +4 -0
- data/lib/aws-sdk-core/client.rb +3 -1
- data/lib/aws-sdk-core/client_stubs.rb +34 -0
- data/lib/aws-sdk-core/endpoint_cache.rb +188 -0
- data/lib/aws-sdk-core/errors.rb +24 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +167 -0
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +62 -0
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +2 -0
- data/lib/aws-sdk-core/plugins/retry_errors.rb +21 -1
- data/lib/aws-sdk-core/plugins/s3_control_dns.rb +3 -1
- data/lib/aws-sdk-core/shared_config.rb +7 -0
- data/lib/aws-sdk-core/version.rb +1 -1
- data/lib/seahorse/client/configuration.rb +7 -1
- data/lib/seahorse/model/api.rb +4 -0
- data/lib/seahorse/model/operation.rb +9 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0071e4fe3106f7b8a5536ba25a6460aa2b87dbee
|
4
|
+
data.tar.gz: 7cb903f9379b80c8864c6a5e71ed7f46af7f8138
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2c4f2bf73e0cae8cea8d73d69eee330177c1f78b869fe58f4722ebeb667ef5da961c3847f948f84c5db534eddc63fa5602922d0ba61076b56ffba13062289fa
|
7
|
+
data.tar.gz: 93cef4a5cf1992ed98b4174775b9efd0761abfefb212e24d7d284eabe06c6f43a5f9661a9951df438f2796b2712746ffc37d75f1dc7d594a44306452bfd7e515
|
@@ -1511,7 +1511,12 @@
|
|
1511
1511
|
"mouthUp",
|
1512
1512
|
"mouthDown",
|
1513
1513
|
"leftPupil",
|
1514
|
-
"rightPupil"
|
1514
|
+
"rightPupil",
|
1515
|
+
"upperJawlineLeft",
|
1516
|
+
"midJawlineLeft",
|
1517
|
+
"chinBottom",
|
1518
|
+
"midJawlineRight",
|
1519
|
+
"upperJawlineRight"
|
1515
1520
|
]
|
1516
1521
|
},
|
1517
1522
|
"Landmarks":{
|
data/lib/aws-sdk-core.rb
CHANGED
@@ -200,6 +200,7 @@ module Aws
|
|
200
200
|
autoload :EagerLoader, 'aws-sdk-core/eager_loader'
|
201
201
|
autoload :ECSCredentials, 'aws-sdk-core/ecs_credentials'
|
202
202
|
autoload :EndpointProvider, 'aws-sdk-core/endpoint_provider'
|
203
|
+
autoload :EndpointCache, 'aws-sdk-core/endpoint_cache'
|
203
204
|
autoload :Errors, 'aws-sdk-core/errors'
|
204
205
|
autoload :IniParser, 'aws-sdk-core/ini_parser'
|
205
206
|
autoload :InstanceProfileCredentials, 'aws-sdk-core/instance_profile_credentials'
|
@@ -259,6 +260,8 @@ module Aws
|
|
259
260
|
autoload :HelpfulSocketErrors, 'aws-sdk-core/plugins/helpful_socket_errors'
|
260
261
|
autoload :IdempotencyToken, 'aws-sdk-core/plugins/idempotency_token'
|
261
262
|
autoload :JsonvalueConverter, 'aws-sdk-core/plugins/jsonvalue_converter'
|
263
|
+
autoload :EndpointDiscovery, 'aws-sdk-core/plugins/endpoint_discovery'
|
264
|
+
autoload :EndpointPattern, 'aws-sdk-core/plugins/endpoint_pattern'
|
262
265
|
autoload :Logging, 'aws-sdk-core/plugins/logging'
|
263
266
|
autoload :MachineLearningPredictEndpoint, 'aws-sdk-core/plugins/machine_learning_predict_endpoint'
|
264
267
|
autoload :ParamConverter, 'aws-sdk-core/plugins/param_converter'
|
@@ -575,10 +578,10 @@ module Aws
|
|
575
578
|
service_added do |name, svc_module, options|
|
576
579
|
if paginators = options[:paginators]
|
577
580
|
paginators = Json.load_file(paginators) unless Hash === paginators
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
581
|
+
paginators['pagination'].each do |n, rules|
|
582
|
+
op_name = Seahorse::Util.underscore(n)
|
583
|
+
operation = svc_module::Client.api.operation(op_name)
|
584
|
+
operation[:pager] = Pager.new(rules)
|
582
585
|
end
|
583
586
|
end
|
584
587
|
end
|
@@ -58,9 +58,20 @@ module Aws
|
|
58
58
|
api = Seahorse::Model::Api.new
|
59
59
|
api.metadata = definition['metadata'] || {}
|
60
60
|
api.version = api.metadata['apiVersion']
|
61
|
+
if op = has_endpoint_operation?(definition['operations'])
|
62
|
+
api.endpoint_operation = op
|
63
|
+
end
|
61
64
|
api
|
62
65
|
end
|
63
66
|
|
67
|
+
def has_endpoint_operation?(ops)
|
68
|
+
return nil if ops.nil?
|
69
|
+
ops.each do |name, op|
|
70
|
+
return underscore(name) if op['endpointoperation']
|
71
|
+
end
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
64
75
|
def build_shape_map(definition, api, docs)
|
65
76
|
shapes = definition['shapes'] || {}
|
66
77
|
api.metadata['shapes'] = ShapeMap.new(shapes, docs: docs)
|
@@ -76,17 +87,29 @@ module Aws
|
|
76
87
|
def build_operation(name, definition, shapes, docs)
|
77
88
|
http = definition['http'] || {}
|
78
89
|
op = Seahorse::Model::Operation.new
|
79
|
-
op.name = name
|
90
|
+
op.name = definition['name'] || name
|
80
91
|
op.http_method = http['method']
|
81
92
|
op.http_request_uri = http['requestUri'] || '/'
|
82
93
|
op.documentation = docs.operation_docs(name)
|
83
94
|
op.deprecated = !!definition['deprecated']
|
95
|
+
op.endpoint_operation = !!definition['endpointoperation']
|
84
96
|
op.input = shapes.shape_ref(definition['input'])
|
85
97
|
op.output = shapes.shape_ref(definition['output'])
|
86
98
|
op['authtype'] = definition['authtype'] unless definition['authtype'].nil?
|
87
99
|
(definition['errors'] || []).each do |error|
|
88
100
|
op.errors << shapes.shape_ref(error)
|
89
101
|
end
|
102
|
+
if definition['endpointdiscovery']
|
103
|
+
op.endpoint_discovery = {}
|
104
|
+
definition['endpointdiscovery'].each do |k, v|
|
105
|
+
op.endpoint_discovery[k] = v
|
106
|
+
end
|
107
|
+
elsif definition['endpoint']
|
108
|
+
op.endpoint_pattern = {}
|
109
|
+
definition['endpoint'].each do |k, v|
|
110
|
+
op.endpoint_pattern[k] = v
|
111
|
+
end
|
112
|
+
end
|
90
113
|
op
|
91
114
|
end
|
92
115
|
|
@@ -94,7 +94,9 @@ module Aws
|
|
94
94
|
plugins('Amazon CloudSearch Domain',
|
95
95
|
add: %w(Aws::Plugins::CSDConditionalSigning
|
96
96
|
Aws::Plugins::CSDSwitchToPost),
|
97
|
-
remove: %w(Aws::Plugins::RegionalEndpoint
|
97
|
+
remove: %w(Aws::Plugins::RegionalEndpoint
|
98
|
+
Aws::Plugins::EndpointPattern
|
99
|
+
Aws::Plugins::EndpointDiscovery),
|
98
100
|
)
|
99
101
|
|
100
102
|
plugins('Amazon DynamoDB', add: %w(
|
@@ -54,6 +54,10 @@ module Aws
|
|
54
54
|
location_name = meta.delete('locationName')
|
55
55
|
location_name ||= options[:member_name] unless location == 'headers'
|
56
56
|
documentation = @docs.shape_ref_docs(shape.name, options[:target])
|
57
|
+
if meta['hostLabel']
|
58
|
+
# used for endpoint pattern
|
59
|
+
meta['hostLabelName'] = options[:member_name]
|
60
|
+
end
|
57
61
|
|
58
62
|
ShapeRef.new(
|
59
63
|
shape: shape,
|
data/lib/aws-sdk-core/client.rb
CHANGED
@@ -17,7 +17,9 @@ module Aws
|
|
17
17
|
'Aws::Plugins::ResponsePaging',
|
18
18
|
'Aws::Plugins::StubResponses',
|
19
19
|
'Aws::Plugins::IdempotencyToken',
|
20
|
-
'Aws::Plugins::JsonvalueConverter'
|
20
|
+
'Aws::Plugins::JsonvalueConverter',
|
21
|
+
'Aws::Plugins::EndpointDiscovery',
|
22
|
+
'Aws::Plugins::EndpointPattern'
|
21
23
|
]
|
22
24
|
|
23
25
|
# @api private
|
@@ -18,6 +18,19 @@ module Aws
|
|
18
18
|
end
|
19
19
|
@config.stub_responses = true
|
20
20
|
end
|
21
|
+
|
22
|
+
# When a client is stubbed allow the user to access the requests made
|
23
|
+
@api_requests = []
|
24
|
+
|
25
|
+
requests = @api_requests
|
26
|
+
self.handle do |context|
|
27
|
+
requests << {
|
28
|
+
operation_name: context.operation_name,
|
29
|
+
params: context.params,
|
30
|
+
context: context
|
31
|
+
}
|
32
|
+
@handler.call(context)
|
33
|
+
end
|
21
34
|
end
|
22
35
|
|
23
36
|
# Configures what data / errors should be returned from the named operation
|
@@ -167,6 +180,27 @@ module Aws
|
|
167
180
|
end
|
168
181
|
end
|
169
182
|
|
183
|
+
# Allows you to access all of the requests that the stubbed client has made
|
184
|
+
#
|
185
|
+
# @params [Boolean] exclude_presign Setting to true for filtering out not sent requests from
|
186
|
+
# generating presigned urls. Default to false.
|
187
|
+
# @return [Array] Returns an array of the api requests made, each request object contains the
|
188
|
+
# :operation_name, :params, and :context of the request.
|
189
|
+
# @raise [NotImplementedError] Raises `NotImplementedError` when the client is not stubbed
|
190
|
+
def api_requests(options = {})
|
191
|
+
if config.stub_responses
|
192
|
+
if options[:exclude_presign]
|
193
|
+
@api_requests.reject {|req| req[:context][:presigned_url] }
|
194
|
+
else
|
195
|
+
@api_requests
|
196
|
+
end
|
197
|
+
else
|
198
|
+
msg = 'This method is only implemented for stubbed clients, and is '
|
199
|
+
msg << 'available when you enable stubbing in the constructor with `stub_responses: true`'
|
200
|
+
raise NotImplementedError.new(msg)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
170
204
|
# Generates and returns stubbed response data from the named operation.
|
171
205
|
#
|
172
206
|
# s3 = Aws::S3::Client.new
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module Aws
|
2
|
+
# @api private
|
3
|
+
# a LRU cache caching endpoints data
|
4
|
+
class EndpointCache
|
5
|
+
|
6
|
+
# default cache entries limit
|
7
|
+
MAX_ENTRIES = 1000
|
8
|
+
|
9
|
+
# default max threads pool size
|
10
|
+
MAX_THREADS = 10
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@max_entries = options[:max_entries] || MAX_ENTRIES
|
14
|
+
@entries = {} # store endpoints
|
15
|
+
@max_threads = options[:max_threads] || MAX_THREADS
|
16
|
+
@pool = {} # store polling threads
|
17
|
+
@mutex = Mutex.new
|
18
|
+
@require_identifier = nil # whether endpoint operation support identifier
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Integer] Max size limit of cache
|
22
|
+
attr_reader :max_entries
|
23
|
+
|
24
|
+
# @return [Integer] Max count of polling threads
|
25
|
+
attr_reader :max_threads
|
26
|
+
|
27
|
+
# return [Hash] Polling threads pool
|
28
|
+
attr_reader :pool
|
29
|
+
|
30
|
+
# @param [String] key
|
31
|
+
# @return [Endpoint]
|
32
|
+
def [](key)
|
33
|
+
@mutex.synchronize do
|
34
|
+
# fetching an existing endpoint delete it and then append it
|
35
|
+
endpoint = @entries[key]
|
36
|
+
if endpoint
|
37
|
+
@entries.delete(key)
|
38
|
+
@entries[key] = endpoint
|
39
|
+
end
|
40
|
+
endpoint
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [String] key
|
45
|
+
# @param [Hash] value
|
46
|
+
def []=(key, value)
|
47
|
+
@mutex.synchronize do
|
48
|
+
# delete the least recent used endpoint when cache is full
|
49
|
+
unless @entries.size < @max_entries
|
50
|
+
old_key, _ = @entries.shift
|
51
|
+
self.delete_polling_thread(old_key)
|
52
|
+
end
|
53
|
+
# delete old value if exists
|
54
|
+
@entries.delete(key)
|
55
|
+
@entries[key] = Endpoint.new(value.to_hash)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# checking whether an unexpired endpoint key exists in cache
|
60
|
+
# @param [String] key
|
61
|
+
# @return [Boolean]
|
62
|
+
def key?(key)
|
63
|
+
if @entries.key?(key) && (@entries[key].nil? || @entries[key].expired?)
|
64
|
+
self.delete(key)
|
65
|
+
end
|
66
|
+
@entries.key?(key)
|
67
|
+
end
|
68
|
+
|
69
|
+
# checking whether an polling thread exist for the key
|
70
|
+
# @param [String] key
|
71
|
+
# @return [Boolean]
|
72
|
+
def threads_key?(key)
|
73
|
+
@pool.key?(key)
|
74
|
+
end
|
75
|
+
|
76
|
+
# remove entry only
|
77
|
+
# @param [String] key
|
78
|
+
def delete(key)
|
79
|
+
@mutex.synchronize do
|
80
|
+
@entries.delete(key)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# kill the old polling thread and remove it from pool
|
85
|
+
# @param [String] key
|
86
|
+
def delete_polling_thread(key)
|
87
|
+
Thread.kill(@pool[key]) if self.threads_key?(key)
|
88
|
+
@pool.delete(key)
|
89
|
+
end
|
90
|
+
|
91
|
+
# update cache with requests (using service endpoint operation)
|
92
|
+
# to fetch endpoint list (with identifiers when available)
|
93
|
+
# @param [String] key
|
94
|
+
# @param [RequestContext] ctx
|
95
|
+
def update(key, ctx)
|
96
|
+
resp = _request_endpoint(ctx)
|
97
|
+
if resp && resp.endpoints
|
98
|
+
resp.endpoints.each { |e| self[key] = e }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# extract the key to be used in the cache from request context
|
103
|
+
# @param [RequestContext] ctx
|
104
|
+
# @return [String]
|
105
|
+
def extract_key(ctx)
|
106
|
+
parts = []
|
107
|
+
# fetching from cred provider directly gives warnings
|
108
|
+
parts << ctx.config.credentials.credentials.access_key_id
|
109
|
+
if _endpoint_operation_identifier(ctx)
|
110
|
+
parts << ctx.operation_name
|
111
|
+
ctx.operation.input.shape.members.inject(parts) do |p, (name, ref)|
|
112
|
+
p << ctx.params[name] if ref["endpointdiscoveryid"]
|
113
|
+
p
|
114
|
+
end
|
115
|
+
end
|
116
|
+
parts.join('_')
|
117
|
+
end
|
118
|
+
|
119
|
+
# update polling threads pool
|
120
|
+
# param [String] key
|
121
|
+
# param [Thread] thread
|
122
|
+
def update_polling_pool(key, thread)
|
123
|
+
unless @pool.size < @max_threads
|
124
|
+
_, thread = @pool.shift
|
125
|
+
Thread.kill(thread)
|
126
|
+
end
|
127
|
+
@pool[key] = thread
|
128
|
+
end
|
129
|
+
|
130
|
+
# kill all polling threads
|
131
|
+
def stop_polling!
|
132
|
+
@pool.each { |_, t| Thread.kill(t) }
|
133
|
+
@pool = {}
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def _request_endpoint(ctx)
|
139
|
+
params = {}
|
140
|
+
if _endpoint_operation_identifier(ctx)
|
141
|
+
# build identifier params when available
|
142
|
+
params[:operation] = ctx.operation.name
|
143
|
+
ctx.operation.input.shape.members.inject(params) do |p, (name, ref)|
|
144
|
+
if ref["endpointdiscoveryid"]
|
145
|
+
p[:identifiers] ||= {}
|
146
|
+
p[:identifiers][ref.location_name] = ctx.params[name]
|
147
|
+
end
|
148
|
+
p
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
begin
|
153
|
+
endpoint_operation_name = ctx.config.api.endpoint_operation
|
154
|
+
ctx.client.send(endpoint_operation_name, params)
|
155
|
+
rescue Aws::Errors::ServiceError
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def _endpoint_operation_identifier(ctx)
|
161
|
+
return @require_identifier unless @require_identifier.nil?
|
162
|
+
operation_name = ctx.config.api.endpoint_operation
|
163
|
+
operation = ctx.config.api.operation(operation_name)
|
164
|
+
@require_identifier = operation.input.shape.members.any?
|
165
|
+
end
|
166
|
+
|
167
|
+
class Endpoint
|
168
|
+
|
169
|
+
# default endpoint cache time, 1 minute
|
170
|
+
CACHE_PERIOD = 1
|
171
|
+
|
172
|
+
def initialize(options)
|
173
|
+
@address = options.fetch(:address)
|
174
|
+
@cache_period = options[:cache_period_in_minutes] || CACHE_PERIOD
|
175
|
+
@created_time = Time.now
|
176
|
+
end
|
177
|
+
|
178
|
+
# [String] valid URI address (with path)
|
179
|
+
attr_reader :address
|
180
|
+
|
181
|
+
def expired?
|
182
|
+
Time.now - @created_time > @cache_period * 60
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
data/lib/aws-sdk-core/errors.rb
CHANGED
@@ -53,6 +53,30 @@ module Aws
|
|
53
53
|
# Raised when a {Service} is constructed and region is not specified.
|
54
54
|
class MissingRegionError < ArgumentError; end
|
55
55
|
|
56
|
+
# Rasied when endpoint discovery failed for operations
|
57
|
+
# that requires endpoints from endpoint discovery
|
58
|
+
class EndpointDiscoveryError < RuntimeError
|
59
|
+
def initialize(*args)
|
60
|
+
msg = 'Endpoint discovery failed for the operation or discovered endpoint is not working, '\
|
61
|
+
'request will keep failing until endpoint discovery succeeds or :endpoint option is provided.'
|
62
|
+
super(msg)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# raised when hostLabel member is not provided
|
67
|
+
# at operation input when endpoint trait is available
|
68
|
+
# with 'hostPrefix' requirement
|
69
|
+
class MissingEndpointHostLabelValue < RuntimeError
|
70
|
+
|
71
|
+
def initialize(name)
|
72
|
+
msg = "Missing required parameter #{name} to construct"\
|
73
|
+
" endpoint host prefix. You can disable host prefix by"\
|
74
|
+
" setting :disable_host_prefix_injection to `true`."
|
75
|
+
super(msg)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
56
80
|
# Raised when attempting to connect to an endpoint and a `SocketError`
|
57
81
|
# is received from the HTTP client. This error is typically the result
|
58
82
|
# of configuring an invalid `:region`.
|
@@ -0,0 +1,167 @@
|
|
1
|
+
module Aws
|
2
|
+
module Plugins
|
3
|
+
|
4
|
+
# Enables Endpoint Discovery per service when supported
|
5
|
+
#
|
6
|
+
# @seahorse.client.option [Boolean] :endpoint_discovery When
|
7
|
+
# set to `true`, endpoint discovery will be enabled for
|
8
|
+
# operations when available. Defaults to `false`.
|
9
|
+
#
|
10
|
+
# @seahorse.client.option [Integer] :endpoint_cache_max_entries
|
11
|
+
# Used for the maximum size limit of the LRU cache storing endpoints data
|
12
|
+
# for endpoint discovery enabled operations. Defaults to 1000.
|
13
|
+
#
|
14
|
+
# @seahorse.client.option [Integer] :endpoint_cache_max_threads
|
15
|
+
# Used for the maximum threads in use for polling endpoints to be cached,
|
16
|
+
# defaults to 10.
|
17
|
+
#
|
18
|
+
# @seahorse.client.option [Integer] :endpoint_cache_poll_interval
|
19
|
+
# When :endpoint_discovery and :active_endpoint_cache is enabled,
|
20
|
+
# Use this option to config the time interval in seconds for making
|
21
|
+
# requests fetching endpoints information. Defaults to 60 sec.
|
22
|
+
#
|
23
|
+
# @seahorse.client.option [Boolean] :active_endpoint_cache
|
24
|
+
# When set to `true`, a thread polling for endpoints will be running in
|
25
|
+
# the background every 60 secs (default). Defaults to `false`.
|
26
|
+
class EndpointDiscovery < Seahorse::Client::Plugin
|
27
|
+
|
28
|
+
option(:endpoint_discovery, false) do |cfg|
|
29
|
+
resolve_endpoint_discovery(cfg)
|
30
|
+
end
|
31
|
+
|
32
|
+
option(:endpoint_cache_max_entries, 1000)
|
33
|
+
|
34
|
+
option(:endpoint_cache_max_threads, 10)
|
35
|
+
|
36
|
+
option(:endpoint_cache_poll_interval, 60)
|
37
|
+
|
38
|
+
option(:endpoint_cache) do |cfg|
|
39
|
+
Aws::EndpointCache.new(
|
40
|
+
max_entries: cfg.endpoint_cache_max_entries,
|
41
|
+
max_threads: cfg.endpoint_cache_max_threads
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
option(:active_endpoint_cache, false)
|
46
|
+
|
47
|
+
def add_handlers(handlers, config)
|
48
|
+
handlers.add(Handler, priority: 90) if config.regional_endpoint
|
49
|
+
end
|
50
|
+
|
51
|
+
class Handler < Seahorse::Client::Handler
|
52
|
+
|
53
|
+
def call(context)
|
54
|
+
if context.operation.endpoint_operation
|
55
|
+
context.http_request.headers['x-amz-api-version'] = context.config.api.version
|
56
|
+
_apply_endpoint_discovery_user_agent(context)
|
57
|
+
elsif discovery_cfg = context.operation.endpoint_discovery
|
58
|
+
endpoint = _discover_endpoint(
|
59
|
+
context,
|
60
|
+
str_2_bool(discovery_cfg["required"])
|
61
|
+
)
|
62
|
+
context.http_request.endpoint = _valid_uri(endpoint.address) if endpoint
|
63
|
+
if endpoint || context.config.endpoint_discovery
|
64
|
+
_apply_endpoint_discovery_user_agent(context)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@handler.call(context)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def _valid_uri(address)
|
73
|
+
# returned address can be missing scheme
|
74
|
+
if address.start_with?('http')
|
75
|
+
URI.parse(address)
|
76
|
+
else
|
77
|
+
URI.parse("https://" + address)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def _apply_endpoint_discovery_user_agent(ctx)
|
82
|
+
if ctx.config.user_agent_suffix.nil?
|
83
|
+
ctx.config.user_agent_suffix = "endpoint-discovery"
|
84
|
+
elsif !ctx.config.user_agent_suffix.include? "endpoint-discovery"
|
85
|
+
ctx.config.user_agent_suffix += "endpoint-discovery"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _discover_endpoint(ctx, required)
|
90
|
+
cache = ctx.config.endpoint_cache
|
91
|
+
key = cache.extract_key(ctx)
|
92
|
+
|
93
|
+
if required
|
94
|
+
# required for the operation
|
95
|
+
unless cache.key?(key)
|
96
|
+
cache.update(key, ctx)
|
97
|
+
end
|
98
|
+
endpoint = cache[key]
|
99
|
+
# hard fail if endpoint is not discovered
|
100
|
+
raise Aws::Errors::EndpointDiscoveryError.new unless endpoint
|
101
|
+
endpoint
|
102
|
+
elsif ctx.config.endpoint_discovery
|
103
|
+
# not required for the operation
|
104
|
+
# but enabled
|
105
|
+
if cache.key?(key)
|
106
|
+
cache[key]
|
107
|
+
elsif ctx.config.active_endpoint_cache
|
108
|
+
# enabled active cache pull
|
109
|
+
interval = ctx.config.endpoint_cache_poll_interval
|
110
|
+
if key.include?('_')
|
111
|
+
# identifier related, kill the previous polling thread by key
|
112
|
+
# because endpoint req params might be changed
|
113
|
+
cache.delete_polling_thread(key)
|
114
|
+
end
|
115
|
+
|
116
|
+
# start a thread for polling endpoints when non-exist
|
117
|
+
unless cache.threads_key?(key)
|
118
|
+
thread = Thread.new do
|
119
|
+
while !cache.key?(key) do
|
120
|
+
cache.update(key, ctx)
|
121
|
+
sleep(interval)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
cache.update_polling_pool(key, thread)
|
125
|
+
end
|
126
|
+
|
127
|
+
cache[key]
|
128
|
+
else
|
129
|
+
# disabled active cache pull
|
130
|
+
# attempt, buit fail soft
|
131
|
+
cache.update(key, ctx)
|
132
|
+
cache[key]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def str_2_bool(str)
|
138
|
+
case str.to_s
|
139
|
+
when "true" then true
|
140
|
+
when "false" then false
|
141
|
+
else
|
142
|
+
nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def self.resolve_endpoint_discovery(cfg)
|
151
|
+
env = ENV['AWS_ENABLE_ENDPOINT_DISCOVERY']
|
152
|
+
shared_cfg = Aws.shared_config.endpoint_discovery(profile: cfg.profile)
|
153
|
+
self.str_2_bool(env) || self.str_2_bool(shared_cfg)
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.str_2_bool(str)
|
157
|
+
case str.to_s
|
158
|
+
when "true" then true
|
159
|
+
when "false" then false
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Aws
|
2
|
+
module Plugins
|
3
|
+
|
4
|
+
# Disable host prefix per operation when available
|
5
|
+
#
|
6
|
+
# @seahorse.client.option [Boolean] :disable_host_prefix_injection
|
7
|
+
# Set to true to disable SDK automatically adding host prefix
|
8
|
+
# to default service endpoint when available.
|
9
|
+
#
|
10
|
+
class EndpointPattern < Seahorse::Client::Plugin
|
11
|
+
|
12
|
+
option(:disable_host_prefix_injection, false)
|
13
|
+
|
14
|
+
def add_handlers(handlers, config)
|
15
|
+
if config.regional_endpoint && !config.disable_host_prefix_injection
|
16
|
+
handlers.add(Handler, priority: 90)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Handler < Seahorse::Client::Handler
|
21
|
+
|
22
|
+
def call(context)
|
23
|
+
endpoint_trait = context.operation.endpoint_pattern
|
24
|
+
if endpoint_trait && !endpoint_trait.empty?
|
25
|
+
_apply_endpoint_trait(context, endpoint_trait)
|
26
|
+
end
|
27
|
+
@handler.call(context)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def _apply_endpoint_trait(context, trait)
|
33
|
+
# currently only support host pattern
|
34
|
+
ori_host = context.http_request.endpoint.host
|
35
|
+
if pattern = trait['hostPrefix']
|
36
|
+
host_prefix = pattern.gsub(/\{.+?\}/) do |label|
|
37
|
+
label = label.delete("{}")
|
38
|
+
_replace_label_value(
|
39
|
+
ori_host, label, context.operation.input, context.params)
|
40
|
+
end
|
41
|
+
context.http_request.endpoint.host = host_prefix + context.http_request.endpoint.host
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _replace_label_value(ori, label, input_ref, params)
|
46
|
+
name = nil
|
47
|
+
input_ref.shape.members.each do |m_name, ref|
|
48
|
+
if ref['hostLabel'] && ref['hostLabelName'] == label
|
49
|
+
name = m_name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
if name.nil? || params[name].nil?
|
53
|
+
raise Errors::MissingEndpointHostLabelValue.new(name)
|
54
|
+
end
|
55
|
+
params[name]
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -71,6 +71,25 @@ module Aws
|
|
71
71
|
(500..599).include?(@http_status_code)
|
72
72
|
end
|
73
73
|
|
74
|
+
def endpoint_discovery?(context)
|
75
|
+
return false unless context.operation.endpoint_discovery
|
76
|
+
|
77
|
+
if @http_status_code == 421 ||
|
78
|
+
extract_name(@error) == 'InvalidEndpointException'
|
79
|
+
@error = Errors::EndpointDiscoveryError.new
|
80
|
+
end
|
81
|
+
|
82
|
+
# When endpoint discovery error occurs
|
83
|
+
# evict the endpoint from cache
|
84
|
+
if @error.is_a?(Errors::EndpointDiscoveryError)
|
85
|
+
key = context.config.endpoint_cache.extract_key(context)
|
86
|
+
context.config.endpoint_cache.delete(key)
|
87
|
+
true
|
88
|
+
else
|
89
|
+
false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
74
93
|
private
|
75
94
|
|
76
95
|
def extract_name(error)
|
@@ -135,7 +154,8 @@ module Aws
|
|
135
154
|
error.throttling_error? or
|
136
155
|
error.checksum? or
|
137
156
|
error.networking? or
|
138
|
-
error.server?
|
157
|
+
error.server? or
|
158
|
+
error.endpoint_discovery?(context)
|
139
159
|
end
|
140
160
|
|
141
161
|
def refreshable_credentials?(context)
|
@@ -128,6 +128,13 @@ module Aws
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
+
def endpoint_discovery(opts = {})
|
132
|
+
p = opts[:profile] || @profile_name
|
133
|
+
if @config_enabled && @parsed_config
|
134
|
+
@parsed_config.fetch(p, {})["endpoint_discovery_enabled"]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
131
138
|
private
|
132
139
|
def credentials_present?
|
133
140
|
(@parsed_credentials && !@parsed_credentials.empty?) ||
|
data/lib/aws-sdk-core/version.rb
CHANGED
@@ -197,7 +197,13 @@ module Seahorse
|
|
197
197
|
|
198
198
|
def value_at(opt_name)
|
199
199
|
value = @struct[opt_name]
|
200
|
-
value.is_a?(Defaults)
|
200
|
+
if value.is_a?(Defaults)
|
201
|
+
# this config value is used by endpoint discovery etc
|
202
|
+
@struct[:regional_endpoint] = true if opt_name == :endpoint
|
203
|
+
resolve_defaults(opt_name, value)
|
204
|
+
else
|
205
|
+
value
|
206
|
+
end
|
201
207
|
end
|
202
208
|
|
203
209
|
def resolve_defaults(opt_name, defaults)
|
data/lib/seahorse/model/api.rb
CHANGED
@@ -5,6 +5,7 @@ module Seahorse
|
|
5
5
|
def initialize
|
6
6
|
@metadata = {}
|
7
7
|
@operations = {}
|
8
|
+
@endpoint_operation = nil
|
8
9
|
end
|
9
10
|
|
10
11
|
# @return [String, nil]
|
@@ -13,6 +14,9 @@ module Seahorse
|
|
13
14
|
# @return [Hash]
|
14
15
|
attr_accessor :metadata
|
15
16
|
|
17
|
+
# @return [Symbol|nil]
|
18
|
+
attr_accessor :endpoint_operation
|
19
|
+
|
16
20
|
def operations(&block)
|
17
21
|
if block_given?
|
18
22
|
@operations.each(&block)
|
@@ -22,9 +22,18 @@ module Seahorse
|
|
22
22
|
# @return [Boolean]
|
23
23
|
attr_accessor :deprecated
|
24
24
|
|
25
|
+
# @return [Boolean]
|
26
|
+
attr_accessor :endpoint_operation
|
27
|
+
|
28
|
+
# @return [Hash]
|
29
|
+
attr_accessor :endpoint_discovery
|
30
|
+
|
25
31
|
# @return [String, nil]
|
26
32
|
attr_accessor :documentation
|
27
33
|
|
34
|
+
# @return [Hash, nil]
|
35
|
+
attr_accessor :endpoint_pattern
|
36
|
+
|
28
37
|
# @return [ShapeRef, nil]
|
29
38
|
attr_accessor :input
|
30
39
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-sdk-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.11.
|
4
|
+
version: 2.11.176
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jmespath
|
@@ -765,6 +765,7 @@ files:
|
|
765
765
|
- lib/aws-sdk-core/elastictranscoder.rb
|
766
766
|
- lib/aws-sdk-core/empty_structure.rb
|
767
767
|
- lib/aws-sdk-core/emr.rb
|
768
|
+
- lib/aws-sdk-core/endpoint_cache.rb
|
768
769
|
- lib/aws-sdk-core/endpoint_provider.rb
|
769
770
|
- lib/aws-sdk-core/errors.rb
|
770
771
|
- lib/aws-sdk-core/firehose.rb
|
@@ -848,6 +849,8 @@ files:
|
|
848
849
|
- lib/aws-sdk-core/plugins/dynamodb_simple_attributes.rb
|
849
850
|
- lib/aws-sdk-core/plugins/ec2_copy_encrypted_snapshot.rb
|
850
851
|
- lib/aws-sdk-core/plugins/ec2_region_validation.rb
|
852
|
+
- lib/aws-sdk-core/plugins/endpoint_discovery.rb
|
853
|
+
- lib/aws-sdk-core/plugins/endpoint_pattern.rb
|
851
854
|
- lib/aws-sdk-core/plugins/glacier_account_id.rb
|
852
855
|
- lib/aws-sdk-core/plugins/glacier_api_version.rb
|
853
856
|
- lib/aws-sdk-core/plugins/glacier_checksums.rb
|