aws-sdk-core 3.36.0 → 3.37.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '083dd2b29c24dd42e393906e157ed16992abd9ce'
4
- data.tar.gz: d7aec8220a6df968102325ffc645801d67e7183b
3
+ metadata.gz: 3a0ca80cd27bbc952ef138198462d128f8586206
4
+ data.tar.gz: f45b8a21bbefd877679e6f9eb61b5d20e53377a7
5
5
  SHA512:
6
- metadata.gz: 85b1ce5dc4e283f2407e9718e298b82773505cdb13b53e9734e176c05e130e691d7329d89e8e51c9c81cbb2dd6e3c3a443ac5bd2bb31422424d5952ff2650dac
7
- data.tar.gz: 5c9cdcfdf9029fd8c0177859097fde46d0c48f8bcfc03361ff5261be6cf9ca0bc6ce71ad4bf8f6ac69d4e5017d09ebc5a0e5bba9ca97c8d6b7d7c1441962ba01
6
+ metadata.gz: 417e4adb9bd6a423160f6ce7a2fed489d77f46bf685535588a38145832d07dee582f674c501f622207129496502fcaebf36cac2a76fd0a73244827c0f6e6ad86
7
+ data.tar.gz: f2299177e51157ec28c44d7a5eed130c3a3bb3b50ca1f717291907b34b05c221442cd786a7101ab83f5f9cb2db174f8e7dee0ba28a07d85dba6cef3711c63464
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.36.0
1
+ 3.37.0
@@ -64,9 +64,14 @@ require_relative 'aws-sdk-core/xml'
64
64
  require_relative 'aws-sdk-core/json'
65
65
 
66
66
  # event stream
67
+
67
68
  require_relative 'aws-sdk-core/binary'
68
69
  require_relative 'aws-sdk-core/event_emitter'
69
70
 
71
+ # endpoint discovery
72
+
73
+ require_relative 'aws-sdk-core/endpoint_cache'
74
+
70
75
  # client metrics
71
76
 
72
77
  require_relative 'aws-sdk-core/client_side_monitoring/request_metrics'
@@ -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
@@ -34,6 +34,16 @@ module Aws
34
34
  end
35
35
  end
36
36
 
37
+ # Rasied when endpoint discovery failed for operations
38
+ # that requires endpoints from endpoint discovery
39
+ class EndpointDiscoveryError < RuntimeError
40
+ def initialize(*args)
41
+ msg = 'Endpoint discovery failed for the operation or discovered endpoint is not working, '\
42
+ 'request will keep failing until endpoint discovery succeeds or :endpoint option is provided.'
43
+ super(msg)
44
+ end
45
+ end
46
+
37
47
  # Raised when EventStream Parser failed to parse
38
48
  # a raw event message
39
49
  class EventStreamParserError < RuntimeError; end
@@ -0,0 +1,160 @@
1
+ module Aws
2
+ module Plugins
3
+ # @api private
4
+ class EndpointDiscovery < Seahorse::Client::Plugin
5
+
6
+ option(:endpoint_discovery,
7
+ default: false,
8
+ doc_type: 'Boolean',
9
+ docstring: <<-DOCS) do |cfg|
10
+ When set to `true`, endpoint discovery will be enabled for operations when available. Defaults to `false`.
11
+ DOCS
12
+ resolve_endpoint_discovery(cfg)
13
+ end
14
+
15
+ option(:endpoint_cache_max_entries,
16
+ default: 1000,
17
+ doc_type: Integer,
18
+ docstring: <<-DOCS
19
+ Used for the maximum size limit of the LRU cache storing endpoints data
20
+ for endpoint discovery enabled operations. Defaults to 1000.
21
+ DOCS
22
+ )
23
+
24
+ option(:endpoint_cache_max_threads,
25
+ default: 10,
26
+ doc_type: Integer,
27
+ docstring: <<-DOCS
28
+ Used for the maximum threads in use for polling endpoints to be cached, defaults to 10.
29
+ DOCS
30
+ )
31
+
32
+ option(:endpoint_cache_poll_interval,
33
+ default: 60,
34
+ doc_type: Integer,
35
+ docstring: <<-DOCS
36
+ When :endpoint_discovery and :active_endpoint_cache is enabled,
37
+ Use this option to config the time interval in seconds for making
38
+ requests fetching endpoints information. Defaults to 60 sec.
39
+ DOCS
40
+ )
41
+
42
+ option(:endpoint_cache) do |cfg|
43
+ Aws::EndpointCache.new(
44
+ max_entries: cfg.endpoint_cache_max_entries,
45
+ max_threads: cfg.endpoint_cache_max_threads
46
+ )
47
+ end
48
+
49
+ option(:active_endpoint_cache,
50
+ default: false,
51
+ doc_type: 'Boolean',
52
+ docstring: <<-DOCS
53
+ When set to `true`, a thread polling for endpoints will be running in
54
+ the background every 60 secs (default). Defaults to `false`.
55
+ DOCS
56
+ )
57
+
58
+ def add_handlers(handlers, config)
59
+ handlers.add(Handler, priority: 90) if config.regional_endpoint
60
+ end
61
+
62
+ class Handler < Seahorse::Client::Handler
63
+
64
+ def call(context)
65
+ if context.operation.endpoint_operation
66
+ context.http_request.headers['x-amz-api-version'] = context.config.api.version
67
+ _apply_endpoint_discovery_user_agent(context)
68
+ elsif discovery_cfg = context.operation.endpoint_discovery
69
+ endpoint = _discover_endpoint(
70
+ context,
71
+ Aws::Util.str_2_bool(discovery_cfg["required"])
72
+ )
73
+ context.http_request.endpoint = _valid_uri(endpoint.address) if endpoint
74
+ if endpoint || context.config.endpoint_discovery
75
+ _apply_endpoint_discovery_user_agent(context)
76
+ end
77
+ end
78
+ @handler.call(context)
79
+ end
80
+
81
+ private
82
+
83
+ def _valid_uri(address)
84
+ # returned address can be missing scheme
85
+ if address.start_with?('http')
86
+ URI.parse(address)
87
+ else
88
+ URI.parse("https://" + address)
89
+ end
90
+ end
91
+
92
+ def _apply_endpoint_discovery_user_agent(ctx)
93
+ if ctx.config.user_agent_suffix.nil?
94
+ ctx.config.user_agent_suffix = "endpoint-discovery"
95
+ elsif !ctx.config.user_agent_suffix.include? "endpoint-discovery"
96
+ ctx.config.user_agent_suffix += "endpoint-discovery"
97
+ end
98
+ end
99
+
100
+ def _discover_endpoint(ctx, required)
101
+ cache = ctx.config.endpoint_cache
102
+ key = cache.extract_key(ctx)
103
+
104
+ if required
105
+ # required for the operation
106
+ unless cache.key?(key)
107
+ cache.update(key, ctx)
108
+ end
109
+ endpoint = cache[key]
110
+ # hard fail if endpoint is not discovered
111
+ raise Aws::Errors::EndpointDiscoveryError.new unless endpoint
112
+ endpoint
113
+ elsif ctx.config.endpoint_discovery
114
+ # not required for the operation
115
+ # but enabled
116
+ if cache.key?(key)
117
+ cache[key]
118
+ elsif ctx.config.active_endpoint_cache
119
+ # enabled active cache pull
120
+ interval = ctx.config.endpoint_cache_poll_interval
121
+ if key.include?('_')
122
+ # identifier related, kill the previous polling thread by key
123
+ # because endpoint req params might be changed
124
+ cache.delete_polling_thread(key)
125
+ end
126
+
127
+ # start a thread for polling endpoints when non-exist
128
+ unless cache.threads_key?(key)
129
+ thread = Thread.new do
130
+ while !cache.key?(key) do
131
+ cache.update(key, ctx)
132
+ sleep(interval)
133
+ end
134
+ end
135
+ cache.update_polling_pool(key, thread)
136
+ end
137
+
138
+ cache[key]
139
+ else
140
+ # disabled active cache pull
141
+ # attempt, buit fail soft
142
+ cache.update(key, ctx)
143
+ cache[key]
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+
150
+ private
151
+
152
+ def self.resolve_endpoint_discovery(cfg)
153
+ env = ENV['AWS_ENABLE_ENDPOINT_DISCOVERY']
154
+ shared_cfg = Aws.shared_config.endpoint_discovery(profile: cfg.profile)
155
+ Aws::Util.str_2_bool(env) || Aws::Util.str_2_bool(shared_cfg)
156
+ end
157
+
158
+ end
159
+ end
160
+ end
@@ -26,6 +26,8 @@ a default `:region` is search for in the following locations:
26
26
  resolve_region(cfg)
27
27
  end
28
28
 
29
+ option(:regional_endpoint, false)
30
+
29
31
  option(:endpoint, doc_type: String, docstring: <<-DOCS) do |cfg|
30
32
  The client endpoint is normally constructed from the `:region`
31
33
  option. You should only configure an `:endpoint` when connecting
@@ -120,12 +120,32 @@ A delay randomiser function used by the default backoff function. Some predefine
120
120
  (500..599).include?(@http_status_code)
121
121
  end
122
122
 
123
+ def endpoint_discovery?(context)
124
+ return false unless context.operation.endpoint_discovery
125
+
126
+ if @http_status_code == 421 ||
127
+ extract_name(@error) == 'InvalidEndpointException'
128
+ @error = Errors::EndpointDiscoveryError.new
129
+ end
130
+
131
+ # When endpoint discovery error occurs
132
+ # evict the endpoint from cache
133
+ if @error.is_a?(Errors::EndpointDiscoveryError)
134
+ key = context.config.endpoint_cache.extract_key(context)
135
+ context.config.endpoint_cache.delete(key)
136
+ true
137
+ else
138
+ false
139
+ end
140
+ end
141
+
123
142
  def retryable?(context)
124
143
  (expired_credentials? and refreshable_credentials?(context)) or
125
144
  throttling_error? or
126
145
  checksum? or
127
146
  networking? or
128
- server?
147
+ server? or
148
+ endpoint_discovery?(context)
129
149
  end
130
150
 
131
151
  private
@@ -136,6 +136,13 @@ module Aws
136
136
  end
137
137
  end
138
138
 
139
+ def endpoint_discovery(opts = {})
140
+ p = opts[:profile] || @profile_name
141
+ if @config_enabled && @parsed_config
142
+ @parsed_config.fetch(p, {})["endpoint_discovery_enabled"]
143
+ end
144
+ end
145
+
139
146
  def credentials_process(profile)
140
147
  validate_profile_exists(profile)
141
148
  @parsed_config[profile]['credential_process']
@@ -52,6 +52,15 @@ module Aws
52
52
  end
53
53
  end
54
54
 
55
+ def str_2_bool(str)
56
+ case str.to_s
57
+ when "true" then true
58
+ when "false" then false
59
+ else
60
+ nil
61
+ end
62
+ end
63
+
55
64
  end
56
65
  end
57
66
  end
@@ -40,6 +40,6 @@ require_relative 'aws-sdk-sts/customizations'
40
40
  # @service
41
41
  module Aws::STS
42
42
 
43
- GEM_VERSION = '3.36.0'
43
+ GEM_VERSION = '3.37.0'
44
44
 
45
45
  end
@@ -15,6 +15,7 @@ require 'aws-sdk-core/plugins/helpful_socket_errors.rb'
15
15
  require 'aws-sdk-core/plugins/retry_errors.rb'
16
16
  require 'aws-sdk-core/plugins/global_configuration.rb'
17
17
  require 'aws-sdk-core/plugins/regional_endpoint.rb'
18
+ require 'aws-sdk-core/plugins/endpoint_discovery.rb'
18
19
  require 'aws-sdk-core/plugins/response_paging.rb'
19
20
  require 'aws-sdk-core/plugins/stub_responses.rb'
20
21
  require 'aws-sdk-core/plugins/idempotency_token.rb'
@@ -45,6 +46,7 @@ module Aws::STS
45
46
  add_plugin(Aws::Plugins::RetryErrors)
46
47
  add_plugin(Aws::Plugins::GlobalConfiguration)
47
48
  add_plugin(Aws::Plugins::RegionalEndpoint)
49
+ add_plugin(Aws::Plugins::EndpointDiscovery)
48
50
  add_plugin(Aws::Plugins::ResponsePaging)
49
51
  add_plugin(Aws::Plugins::StubResponses)
50
52
  add_plugin(Aws::Plugins::IdempotencyToken)
@@ -98,6 +100,10 @@ module Aws::STS
98
100
  #
99
101
  # @option options [String] :access_key_id
100
102
  #
103
+ # @option options [Boolean] :active_endpoint_cache (false)
104
+ # When set to `true`, a thread polling for endpoints will be running in
105
+ # the background every 60 secs (default). Defaults to `false`.
106
+ #
101
107
  # @option options [Boolean] :client_side_monitoring (false)
102
108
  # When `true`, client-side metrics will be collected for all API requests from
103
109
  # this client.
@@ -123,6 +129,21 @@ module Aws::STS
123
129
  # option. You should only configure an `:endpoint` when connecting
124
130
  # to test endpoints. This should be avalid HTTP(S) URI.
125
131
  #
132
+ # @option options [Integer] :endpoint_cache_max_entries (1000)
133
+ # Used for the maximum size limit of the LRU cache storing endpoints data
134
+ # for endpoint discovery enabled operations. Defaults to 1000.
135
+ #
136
+ # @option options [Integer] :endpoint_cache_max_threads (10)
137
+ # Used for the maximum threads in use for polling endpoints to be cached, defaults to 10.
138
+ #
139
+ # @option options [Integer] :endpoint_cache_poll_interval (60)
140
+ # When :endpoint_discovery and :active_endpoint_cache is enabled,
141
+ # Use this option to config the time interval in seconds for making
142
+ # requests fetching endpoints information. Defaults to 60 sec.
143
+ #
144
+ # @option options [Boolean] :endpoint_discovery (false)
145
+ # When set to `true`, endpoint discovery will be enabled for operations when available. Defaults to `false`.
146
+ #
126
147
  # @option options [Aws::Log::Formatter] :log_formatter (Aws::Log::Formatter.default)
127
148
  # The log formatter.
128
149
  #
@@ -1508,7 +1529,7 @@ module Aws::STS
1508
1529
  params: params,
1509
1530
  config: config)
1510
1531
  context[:gem_name] = 'aws-sdk-core'
1511
- context[:gem_version] = '3.36.0'
1532
+ context[:gem_version] = '3.37.0'
1512
1533
  Seahorse::Client::Request.new(handlers, context)
1513
1534
  end
1514
1535
 
@@ -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) ? resolve_defaults(opt_name, value) : value
200
+ if value.is_a?(Defaults)
201
+ # this config value is used by endpoint discovery
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)
@@ -6,6 +6,7 @@ module Seahorse
6
6
  @metadata = {}
7
7
  @operations = {}
8
8
  @authorizers = {}
9
+ @endpoint_operation = nil
9
10
  end
10
11
 
11
12
  # @return [String, nil]
@@ -14,6 +15,9 @@ module Seahorse
14
15
  # @return [Hash]
15
16
  attr_accessor :metadata
16
17
 
18
+ # @return [Symbol|nil]
19
+ attr_accessor :endpoint_operation
20
+
17
21
  def operations(&block)
18
22
  if block_given?
19
23
  @operations.each(&block)
@@ -22,6 +22,12 @@ 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
 
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: 3.36.0
4
+ version: 3.37.0
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-10-30 00:00:00.000000000 Z
11
+ date: 2018-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jmespath
@@ -90,6 +90,7 @@ files:
90
90
  - lib/aws-sdk-core/deprecations.rb
91
91
  - lib/aws-sdk-core/eager_loader.rb
92
92
  - lib/aws-sdk-core/ecs_credentials.rb
93
+ - lib/aws-sdk-core/endpoint_cache.rb
93
94
  - lib/aws-sdk-core/errors.rb
94
95
  - lib/aws-sdk-core/event_emitter.rb
95
96
  - lib/aws-sdk-core/ini_parser.rb
@@ -116,6 +117,7 @@ files:
116
117
  - lib/aws-sdk-core/plugins/client_metrics_plugin.rb
117
118
  - lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb
118
119
  - lib/aws-sdk-core/plugins/credentials_configuration.rb
120
+ - lib/aws-sdk-core/plugins/endpoint_discovery.rb
119
121
  - lib/aws-sdk-core/plugins/event_stream_configuration.rb
120
122
  - lib/aws-sdk-core/plugins/global_configuration.rb
121
123
  - lib/aws-sdk-core/plugins/helpful_socket_errors.rb