From 82a9e7473a87818a6978159096b2ba9add505414 Mon Sep 17 00:00:00 2001 From: Alex Woods Date: Fri, 18 Oct 2024 09:03:18 -0700 Subject: [PATCH] Reapply "Reduce memory usage from aws-partitions (#3122)" This reverts commit c1c38b474abe02ccb4890e0ff4479b299aea62a5. --- .../lib/aws-sdk-code-generator.rb | 1 + .../endpoint_parameter.rb | 190 ++++++++++++++++++ .../views/endpoint_parameters_class.rb | 59 +----- .../views/endpoints_module.rb | 156 ++------------ .../spec/interfaces/plugins/endpoints_spec.rb | 11 +- .../endpoint_parameters_class.mustache | 24 ++- .../templates/endpoints_module.mustache | 24 ++- .../templates/endpoints_plugin.mustache | 11 +- build_tools/services.rb | 4 +- gems/aws-partitions/CHANGELOG.md | 2 + gems/aws-partitions/lib/aws-partitions.rb | 1 + .../lib/aws-partitions/metadata.rb | 32 +++ gems/aws-sdk-core/CHANGELOG.md | 2 + gems/aws-sdk-core/aws-sdk-core.gemspec | 2 +- .../lib/aws-sdk-core/endpoints/matchers.rb | 9 +- .../aws-sdk-core/plugins/regional_endpoint.rb | 69 ++++--- gems/aws-sdk-core/spec/aws/endpoints_spec.rb | 2 +- 17 files changed, 344 insertions(+), 255 deletions(-) create mode 100644 build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/endpoint_parameter.rb create mode 100644 gems/aws-partitions/lib/aws-partitions/metadata.rb diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator.rb index 09fad189182..23fc74b92f2 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator.rb @@ -12,6 +12,7 @@ require_relative 'aws-sdk-code-generator/client_response_structure_example' require_relative 'aws-sdk-code-generator/crosslink' require_relative 'aws-sdk-code-generator/docstring' +require_relative 'aws-sdk-code-generator/endpoint_parameter' require_relative 'aws-sdk-code-generator/hash_formatter' require_relative 'aws-sdk-code-generator/helper' require_relative 'aws-sdk-code-generator/plugin_list' diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/endpoint_parameter.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/endpoint_parameter.rb new file mode 100644 index 00000000000..36d22c08d52 --- /dev/null +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/endpoint_parameter.rb @@ -0,0 +1,190 @@ +# frozen_string_literal: true + +module AwsSdkCodeGenerator + class EndpointParameter + def initialize(name, definition, service, operation=nil) + @name = name + + @value, @source = endpoint_parameter_value(name, definition, service, operation) + + @type = definition['type'] + @built_in = definition['builtIn'] + @default = definition['default'] + @required = definition['required'] + @documentation = "# @!attribute #{key}\n" + if definition['documentation'] + @documentation += " # #{definition['documentation']}\n" + end + if deprecated = definition['deprecated'] + @documentation += " #\n # @deprecated\n" + if deprecated['message'] + @documentation += " # #{deprecated['message']}\n" + end + if deprecated['since'] + @documentation += " # Since: #{deprecated['since']}\n" + end + end + @documentation += " #\n # @return [#{@type}]\n #" + end + + # @return [String] + attr_reader :name + + # @return [String] + attr_reader :documentation + + # @return [Boolean] + attr_reader :required + + # @return [String] + attr_reader :source + + # @return [String] + attr_reader :value + + # @return [String,Boolean,Array] + def default + case @default + when String + "\"#{@default}\"" + else + @default.to_s + end + end + + def default? + !@default.nil? + end + + def validate_required? + required && !default? + end + + def key + Underscore.underscore(name) + end + + private + + # Most to least + # staticContextParams + # contextParam + # operationContextParams + # clientContextParams (always sourced from config) + # Built-In Bindings (sourced from config in most cases, context in some cases to allow operation level overrides) + # Built-in binding default values + # @retyrn [value, source]. source may be one of [operation, config, default] + def endpoint_parameter_value(param_name, param_data, service, operation) + unless operation.nil? + value, source = [ + static_context_param(operation, param_name), 'operation' + ] + value, source = [ + context_param_value(service, operation, param_name), 'operation' + ] unless value + value, source = [ + operation_context_param_value(operation, param_name), 'operation' + ] unless value + end + + value, source = [ + client_context_param_value(service, param_name, param_data), + 'config' + ] unless value + + + # built-ins may be sourced from operation context in some cases + unless value + value, source = built_in_param_value(service, param_data) + end + + [value || 'nil', source || 'default'] + end + + def client_context_param_value(service, param_name, param_data) + if service.api['clientContextParams']&.key?(param_name) && + !param_data['builtIn'] + "config.#{Underscore.underscore(param_name)}" + end + end + + # built-ins may be sourced from operation context in some cases + def built_in_param_value(service, param_data) + source = 'config' + value = + case param_data['builtIn'] + when 'AWS::Region' + 'config.region' + when 'AWS::UseFIPS' + 'config.use_fips_endpoint' + when 'AWS::UseDualStack' + if service.name == 'S3' || service.name == 'S3Control' + source = 'operation' + 'context[:use_dualstack_endpoint]' + else + 'config.use_dualstack_endpoint' + end + when 'AWS::Auth::AccountId' + 'config.credentials.credentials.account_id' + when 'AWS::Auth::AccountIdEndpointMode' + 'config.account_id_endpoint_mode' + when 'AWS::STS::UseGlobalEndpoint' + "config.sts_regional_endpoints == 'legacy'" + when 'AWS::S3::UseGlobalEndpoint' + "config.s3_us_east_1_regional_endpoint == 'legacy'" + when 'AWS::S3::Accelerate' + if service.name == 'S3' || service.name == 'S3Control' + source = 'operation' + 'context[:use_accelerate_endpoint]' + else + 'config.use_accelerate_endpoint' + end + when 'AWS::S3::ForcePathStyle' + 'config.force_path_style' + when 'AWS::S3::UseArnRegion', 'AWS::S3Control::UseArnRegion' + 'config.s3_use_arn_region' + when 'AWS::S3::DisableMultiRegionAccessPoints' + 'config.s3_disable_multiregion_access_points' + when 'SDK::Endpoint' + '(config.endpoint.to_s unless config.regional_endpoint)' + else + source = nil + nil # no value, not a default + end + [value, source] + end + + def context_param_value(service, operation, param_name) + return nil unless operation['input'] + + input_shape = operation['input']['shape'] + members = service.api['shapes'][input_shape].fetch('members', {}) + members.detect do |(member_name, member)| + context_param = member.fetch('contextParam', {}) + if context_param.fetch('name', nil) == param_name + break "context.params[:#{Underscore.underscore(member_name)}]" + end + end + end + + def operation_context_param_value(operation, param_name) + return nil unless operation['input'] + + binding = operation.fetch('operationContextParams', {})[param_name] + + return nil unless binding + + "JMESPath.search(\"#{Underscore.underscore_jmespath(binding['path'])}\", context.params)" + end + + def static_context_param(operation, param_name) + value = operation.fetch('staticContextParams', {}) + .fetch(param_name, {}).fetch('value', nil) + if !value.nil? && value.is_a?(String) + "\"#{value}\"" + else + value + end + end + end +end diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoint_parameters_class.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoint_parameters_class.rb index e0afcbb2786..70843b1519c 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoint_parameters_class.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoint_parameters_class.rb @@ -9,7 +9,7 @@ def initialize(options) @service = options.fetch(:service) if (parameters = @service.endpoint_rules&.fetch('parameters')) @parameters = parameters.map do |k,p| - EndpointParameter.new(k, p) + EndpointParameter.new(k, p, @service) end end end @@ -17,6 +17,11 @@ def initialize(options) # @return [Array] attr_reader :parameters + # @return [Array] + def config_parameters + parameters.select { |p| p.source == 'config' } + end + # @return [String|nil] def generated_src_warning return if @service.protocol == 'api-gateway' @@ -26,58 +31,6 @@ def generated_src_warning def module_name @service.module_name end - - class EndpointParameter - def initialize(name, definition={}) - @name = name - @type = definition['type'] - @built_in = definition['builtIn'] - @default = definition['default'] - @required = definition['required'] - @documentation = "# @!attribute #{underscore_name}\n" - if definition['documentation'] - @documentation += " # #{definition['documentation']}\n" - end - if deprecated = definition['deprecated'] - @documentation += " #\n # @deprecated\n" - if deprecated['message'] - @documentation += " # #{deprecated['message']}\n" - end - if deprecated['since'] - @documentation += " # Since: #{deprecated['since']}\n" - end - end - @documentation += " #\n # @return [#{@type}]\n #" - end - - # @return [String] - attr_reader :name - - # @return [String] - attr_reader :documentation - - # @return [Boolean] - attr_reader :required - - # @return [String,Boolean,Array] - def default - case @default - when String - "\"#{@default}\"" - else - @default.to_s - end - end - - def default? - !@default.nil? - end - - def underscore_name - Underscore.underscore(name) - end - end - end end end diff --git a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb index 0953ad49595..16d9c4298c3 100644 --- a/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb +++ b/build_tools/aws-sdk-code-generator/lib/aws-sdk-code-generator/views/endpoints_module.rb @@ -10,11 +10,12 @@ def initialize(options) @parameters = @service.endpoint_rules.fetch('parameters', {}) @endpoint_classes = @service.api['operations'].each.with_object([]) do - |(name, op), array| - array << EndpointClass.new( + |(name, op), classes| + endpoint_class = EndpointClass.new( name: name, parameters: endpoint_parameters_for_operation(op) ) + classes << endpoint_class unless endpoint_class.parameters.empty? end end @@ -31,161 +32,40 @@ def module_name @service.module_name end + def operation_specific_parameters? + @endpoint_classes.empty? + end + class EndpointClass def initialize(options) @name = options[:name] + @operation = Underscore.underscore(@name) @parameters = options[:parameters] end # @return [String] attr_reader :name - # @return [Array] - attr_reader :parameters - end - - class EndpointParameter - def initialize(options) - @key = options[:key] - @value = options[:value] - @source = options[:source] - @param_data = options[:param_data] - end - - # @return [String] - attr_accessor :key - - # @return [String] - attr_accessor :value - # @return [String] - attr_accessor :source + attr_reader :operation - # @return [Hash] - attr_accessor :param_data - - def static_string? - @source == 'staticContextParam' && value.is_a?(String) - end + # @return [Array] + attr_reader :parameters end - private def endpoint_parameters_for_operation(operation) - @parameters.each.with_object([]) do |(param_name, param_data), endpoint_parameters| - value, source = endpoint_parameter_value( - operation, param_name, param_data - ) - - endpoint_parameters << EndpointParameter.new( - key: Underscore.underscore(param_name), - value: value, - source: source, - param_data: param_data + @parameters.each.with_object([]) do |(param_name, param_data), parameters| + p = EndpointParameter.new( + param_name, + param_data, + @service, + operation ) + parameters << p if p.source == 'operation' end end - - # Most to least - # staticContextParams - # contextParam - # operationContextParams - # clientContextParams - # Built-In Bindings - # Built-in binding default values - def endpoint_parameter_value(operation, param_name, param_data) - value, source = [ - static_context_param(operation, param_name), 'staticContextParam' - ] - value, source = [ - context_param_value(operation, param_name), 'contextParam' - ] unless value - value, source = [ - operation_context_param_value(operation, param_name), 'operationContextParam' - ] unless value - value, source = [ - client_context_param_value(param_name, param_data), - 'clientContextParam' - ] unless value - value, source = [ - built_in_client_context_param_value(param_data), 'builtIn' - ] unless value - - [value || 'nil', source] - end - - def client_context_param_value(param_name, param_data) - if @service.api['clientContextParams']&.key?(param_name) && - !param_data['builtIn'] - "context.config.#{Underscore.underscore(param_name)}" - end - end - - def built_in_client_context_param_value(param_data) - case param_data['builtIn'] - when 'AWS::Region' - 'context.config.region' - when 'AWS::UseFIPS' - 'context.config.use_fips_endpoint' - when 'AWS::UseDualStack' - if @service.name == 'S3' || @service.name == 'S3Control' - 'context[:use_dualstack_endpoint]' - else - 'context.config.use_dualstack_endpoint' - end - when 'AWS::Auth::AccountId' - 'context.config.credentials.credentials.account_id' - when 'AWS::Auth::AccountIdEndpointMode' - 'context.config.account_id_endpoint_mode' - when 'AWS::STS::UseGlobalEndpoint' - "context.config.sts_regional_endpoints == 'legacy'" - when 'AWS::S3::UseGlobalEndpoint' - "context.config.s3_us_east_1_regional_endpoint == 'legacy'" - when 'AWS::S3::Accelerate' - if @service.name == 'S3' || @service.name == 'S3Control' - 'context[:use_accelerate_endpoint]' - else - 'context.config.use_accelerate_endpoint' - end - when 'AWS::S3::ForcePathStyle' - 'context.config.force_path_style' - when 'AWS::S3::UseArnRegion', 'AWS::S3Control::UseArnRegion' - 'context.config.s3_use_arn_region' - when 'AWS::S3::DisableMultiRegionAccessPoints' - 'context.config.s3_disable_multiregion_access_points' - when 'SDK::Endpoint' - 'context.config.regional_endpoint ? nil : context.config.endpoint.to_s' - end - end - - def context_param_value(operation, param_name) - return nil unless operation['input'] - - input_shape = operation['input']['shape'] - members = @service.api['shapes'][input_shape].fetch('members', {}) - members.detect do |(member_name, member)| - context_param = member.fetch('contextParam', {}) - if context_param.fetch('name', nil) == param_name - break "context.params[:#{Underscore.underscore(member_name)}]" - end - end - end - - def operation_context_param_value(operation, param_name) - return nil unless operation['input'] - - binding = operation.fetch('operationContextParams', {})[param_name] - - return nil unless binding - - "JMESPath.search(\"#{Underscore.underscore_jmespath(binding['path'])}\", context.params)" - end - - def static_context_param(operation, param_name) - operation.fetch('staticContextParams', {}) - .fetch(param_name, {}).fetch('value', nil) - end end end end diff --git a/build_tools/aws-sdk-code-generator/spec/interfaces/plugins/endpoints_spec.rb b/build_tools/aws-sdk-code-generator/spec/interfaces/plugins/endpoints_spec.rb index 71c815a7761..20fe230986a 100644 --- a/build_tools/aws-sdk-code-generator/spec/interfaces/plugins/endpoints_spec.rb +++ b/build_tools/aws-sdk-code-generator/spec/interfaces/plugins/endpoints_spec.rb @@ -38,6 +38,7 @@ it 'uses endpoint provider with params to resolve endpoint' do expect_any_instance_of(EndpointsPlugin::EndpointProvider) .to receive(:resolve_endpoint) + .at_least(:once) .with(an_instance_of(EndpointsPlugin::EndpointParameters)) .and_call_original client.operation @@ -71,13 +72,13 @@ it 'maps built ins' do expect(EndpointsBuiltIns::EndpointParameters).to receive(:new) - .with( + .with({ region: region, endpoint: endpoint, use_fips: true, use_dual_stack: true, account_id_endpoint_mode: 'preferred' - ).and_call_original + }).and_call_original client.operation end @@ -124,6 +125,10 @@ EndpointsPrecedence::Client.new(stub_responses: true, region: 'config') end + before(:each) do + client # force client initialization before testing resolution to account for config.endpoint + end + # Most to least # staticContextParams # contextParam @@ -166,7 +171,7 @@ it 'defaults to nil' do client = EndpointsPrecedence::Client.new(stub_responses: true) expect(EndpointsPrecedence::EndpointParameters).to receive(:new) - .with(hash_including(nothing: nil)).and_call_original + .with(hash_including(client_context_param: nil)).and_call_original client.operation end end diff --git a/build_tools/aws-sdk-code-generator/templates/endpoint_parameters_class.mustache b/build_tools/aws-sdk-code-generator/templates/endpoint_parameters_class.mustache index 0b9b3278791..e921ad00164 100644 --- a/build_tools/aws-sdk-code-generator/templates/endpoint_parameters_class.mustache +++ b/build_tools/aws-sdk-code-generator/templates/endpoint_parameters_class.mustache @@ -11,7 +11,7 @@ module {{module_name}} {{/parameters}} EndpointParameters = Struct.new( {{#parameters}} - :{{underscore_name}}, + :{{key}}, {{/parameters}} {{^parameters}} nil @@ -23,23 +23,31 @@ module {{module_name}} class << self PARAM_MAP = { {{#parameters}} - '{{name}}' => :{{underscore_name}}, + '{{name}}' => :{{key}}, {{/parameters}} }.freeze end def initialize(options = {}) {{#parameters}} - self[:{{underscore_name}}] = options[:{{underscore_name}}] + self[:{{key}}] = options[:{{key}}] {{#default?}} - self[:{{underscore_name}}] = {{{default}}} if self[:{{underscore_name}}].nil? + self[:{{key}}] = {{{default}}} if self[:{{key}}].nil? {{/default?}} - {{#required}} - if self[:{{underscore_name}}].nil? - raise ArgumentError, "Missing required EndpointParameter: :{{underscore_name}}" + {{#validate_required?}} + if self[:{{key}}].nil? + raise ArgumentError, "Missing required EndpointParameter: :{{key}}" end - {{/required}} + {{/validate_required?}} {{/parameters}} end + + def self.create(config, options={}) + new({ + {{#config_parameters}} + {{key}}: {{{value}}}, + {{/config_parameters}} + }.merge(options)) + end end end diff --git a/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache b/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache index a93a5860b8a..91e460352fe 100644 --- a/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache +++ b/build_tools/aws-sdk-code-generator/templates/endpoints_module.mustache @@ -11,19 +11,31 @@ module {{module_name}} {{#endpoint_classes}} class {{name}} def self.build(context) - {{module_name}}::EndpointParameters.new( + {{module_name}}::EndpointParameters.create( + context.config, {{#parameters}} - {{#static_string?}} - {{key}}: "{{{value}}}", - {{/static_string?}} - {{^static_string?}} {{key}}: {{{value}}}, - {{/static_string?}} {{/parameters}} ) end end {{/endpoint_classes}} + + def self.parameters_for_operation(context) + {{#operation_specific_parameters?}} + {{module_name}}::EndpointParameters.create(context.config) + {{/operation_specific_parameters?}} + {{^operation_specific_parameters?}} + case context.operation_name + {{#endpoint_classes}} + when :{{operation}} + {{name}}.build(context) + {{/endpoint_classes}} + else + {{module_name}}::EndpointParameters.create(context.config) + end + {{/operation_specific_parameters?}} + end end end diff --git a/build_tools/aws-sdk-code-generator/templates/endpoints_plugin.mustache b/build_tools/aws-sdk-code-generator/templates/endpoints_plugin.mustache index d9647844250..42b84453054 100644 --- a/build_tools/aws-sdk-code-generator/templates/endpoints_plugin.mustache +++ b/build_tools/aws-sdk-code-generator/templates/endpoints_plugin.mustache @@ -34,7 +34,7 @@ The endpoint provider used to resolve endpoints. Any object that responds to class Handler < Seahorse::Client::Handler def call(context) unless context[:discovered_endpoint] - params = parameters_for_operation(context) + params = {{module_name}}::Endpoints.parameters_for_operation(context) endpoint = context.config.endpoint_provider.resolve_endpoint(params) context.http_request.endpoint = endpoint.url @@ -84,15 +84,6 @@ The endpoint provider used to resolve endpoints. Any object that responds to context.http_request.headers[key] = value end end - - def parameters_for_operation(context) - case context.operation_name - {{#endpoint_classes}} - when :{{operation_name}} - {{module_name}}::Endpoints::{{class_name}}.build(context) - {{/endpoint_classes}} - end - end end def add_handlers(handlers, _config) diff --git a/build_tools/services.rb b/build_tools/services.rb index 045bb254e2a..67a5ed670c5 100644 --- a/build_tools/services.rb +++ b/build_tools/services.rb @@ -10,10 +10,10 @@ class ServiceEnumerator MANIFEST_PATH = File.expand_path('../../services.json', __FILE__) # Minimum `aws-sdk-core` version for new gem builds - MINIMUM_CORE_VERSION = "3.207.0" + MINIMUM_CORE_VERSION = "3.210.0" # Minimum `aws-sdk-core` version for new S3 gem builds - MINIMUM_CORE_VERSION_S3 = "3.207.0" + MINIMUM_CORE_VERSION_S3 = "3.210.0" EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration" diff --git a/gems/aws-partitions/CHANGELOG.md b/gems/aws-partitions/CHANGELOG.md index 34a8ea0c89a..22ef1d8a04f 100644 --- a/gems/aws-partitions/CHANGELOG.md +++ b/gems/aws-partitions/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Feature - Add partition metadata module, allowing access without loading entire partitions.json. + 1.991.0 (2024-10-15) ------------------ diff --git a/gems/aws-partitions/lib/aws-partitions.rb b/gems/aws-partitions/lib/aws-partitions.rb index 2e57bcec7d5..5ff38992aed 100644 --- a/gems/aws-partitions/lib/aws-partitions.rb +++ b/gems/aws-partitions/lib/aws-partitions.rb @@ -5,6 +5,7 @@ require_relative 'aws-partitions/partition_list' require_relative 'aws-partitions/region' require_relative 'aws-partitions/service' +require_relative 'aws-partitions/metadata' require 'json' diff --git a/gems/aws-partitions/lib/aws-partitions/metadata.rb b/gems/aws-partitions/lib/aws-partitions/metadata.rb new file mode 100644 index 00000000000..ee2ac0061f4 --- /dev/null +++ b/gems/aws-partitions/lib/aws-partitions/metadata.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Aws + module Partitions + # @api private + module Metadata + class << self + + # aws.partition(region: string) Option + def partition(region) + partition = + partitions.find { |p| p['regions']&.fetch(region, nil) } || + partitions.find { |p| region.match(p['regionRegex']) } || + partitions.find { |p| p['id'] == 'aws' } + + return nil unless partition + + partition['outputs'] + end + + def partitions + @partitions ||= default_partition_metadata + end + + def default_partition_metadata + path = File.expand_path('../../../partitions-metadata.json', __FILE__) + JSON.parse(File.read(path), freeze: true)['partitions'] + end + end + end + end +end \ No newline at end of file diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index 92f50c28c31..d4a9ca22d46 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Feature - reduce memory usage by not using legacy endpoint data unless required. + 3.209.1 (2024-09-25) ------------------ diff --git a/gems/aws-sdk-core/aws-sdk-core.gemspec b/gems/aws-sdk-core/aws-sdk-core.gemspec index 6b393f4bfd3..3ad0917fda7 100644 --- a/gems/aws-sdk-core/aws-sdk-core.gemspec +++ b/gems/aws-sdk-core/aws-sdk-core.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |spec| spec.files = Dir['LICENSE.txt', 'CHANGELOG.md', 'VERSION', 'lib/**/*.rb', 'sig/**/*.rbs', 'ca-bundle.crt'] spec.add_dependency('jmespath', '~> 1', '>= 1.6.1') # necessary for secure jmespath JSON parsing - spec.add_dependency('aws-partitions', '~> 1', '>= 1.651.0') # necessary for new endpoint resolution + spec.add_dependency('aws-partitions', '~> 1', '>= 1.992.0') # necessary for new endpoint resolution spec.add_dependency('aws-sigv4', '~> 1.9') # necessary for s3 express auth/native sigv4a support spec.add_dependency('aws-eventstream', '~> 1', '>= 1.3.0') # necessary for binary eventstream diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/endpoints/matchers.rb b/gems/aws-sdk-core/lib/aws-sdk-core/endpoints/matchers.rb index 542b0abb73c..95ac2b17903 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/endpoints/matchers.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/endpoints/matchers.rb @@ -94,14 +94,7 @@ def self.valid_host_label?(value, allow_sub_domains = false) # aws.partition(value: string) Option def self.aws_partition(value) - partition = - Aws::Partitions.find { |p| p.region?(value) } || - Aws::Partitions.find { |p| value.match(p.region_regex) } || - Aws::Partitions.find { |p| p.name == 'aws' } - - return nil unless partition - - partition.metadata + Aws::Partitions::Metadata.partition(value) end # aws.parseArn(value: string) Option diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb index ede2b2d8b6c..5fc7552c15d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb @@ -20,7 +20,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin * `ENV['AWS_DEFAULT_REGION']` * `~/.aws/credentials` * `~/.aws/config` - DOCS + DOCS resolve_region(cfg) end @@ -35,7 +35,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin * `Aws.config[:sigv4a_signing_region_set]` * `ENV['AWS_SIGV4A_SIGNING_REGION_SET']` * `~/.aws/config` - DOCS + DOCS resolve_sigv4a_signing_region_set(cfg) end @@ -44,7 +44,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin docstring: <<-DOCS) do |cfg| When set to `true`, dualstack enabled endpoints (with `.aws` TLD) will be used if available. - DOCS + DOCS resolve_use_dualstack_endpoint(cfg) end @@ -54,7 +54,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin When set to `true`, fips compatible endpoints will be used if available. When a `fips` region is used, the region is normalized and this config is set to `true`. - DOCS + DOCS resolve_use_fips_endpoint(cfg) end @@ -67,7 +67,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin docstring: <<-DOCS) do |cfg| Setting to true disables use of endpoint URLs provided via environment variables and the shared configuration file. - DOCS + DOCS resolve_ignore_configured_endpoint_urls(cfg) end @@ -75,7 +75,7 @@ class RegionalEndpoint < Seahorse::Client::Plugin The client endpoint is normally constructed from the `:region` option. You should only configure an `:endpoint` when connecting to test or custom endpoints. This should be a valid HTTP(S) URI. - DOCS + DOCS resolve_endpoint(cfg) end @@ -83,6 +83,9 @@ def after_initialize(client) region = client.config.region raise Errors::MissingRegionError if region.nil? || region == '' + # resolve a default endpoint to preserve legacy behavior + initialize_default_endpoint(client) if client.config.endpoint.nil? + region_set = client.config.sigv4a_signing_region_set return if region_set.nil? raise Errors::InvalidRegionSetError unless region_set.is_a?(Array) @@ -93,6 +96,39 @@ def after_initialize(client) client.config.sigv4a_signing_region_set = region_set end + private + + def initialize_default_endpoint(client) + client_module = Object.const_get(client.class.name.rpartition('::').first) + param_class = client_module.const_get(:EndpointParameters) + endpoint_provider = client.config.endpoint_provider + params = param_class.create(client.config) + endpoint = endpoint_provider.resolve_endpoint(params) + client.config.endpoint = endpoint.url + rescue ArgumentError, NameError + # fallback to legacy + client.config.endpoint = resolve_legacy_endpoint(client.config) + end + + # set a default endpoint in config using legacy (endpoints.json) resolver + def resolve_legacy_endpoint(cfg) + endpoint_prefix = cfg.api.metadata['endpointPrefix'] + if cfg.respond_to?(:sts_regional_endpoints) + sts_regional = cfg.sts_regional_endpoints + end + + endpoint = Aws::Partitions::EndpointProvider.resolve( + cfg.region, + endpoint_prefix, + sts_regional, + { + dualstack: cfg.use_dualstack_endpoint, + fips: cfg.use_fips_endpoint + } + ) + URI(endpoint) + end + class << self private @@ -150,7 +186,8 @@ def resolve_endpoint(cfg) # that a custom endpoint has NOT been configured by the user cfg.override_config(:regional_endpoint, true) - resolve_legacy_endpoint(cfg) + # a default endpoint is resolved in after_initialize + nil end # get a custom configured endpoint from ENV or configuration @@ -205,24 +242,6 @@ def handle_legacy_pseudo_regions(cfg) cfg.override_config(:region, new_region) end end - - # set a default endpoint in config using legacy (endpoints.json) resolver - def resolve_legacy_endpoint(cfg) - endpoint_prefix = cfg.api.metadata['endpointPrefix'] - if cfg.respond_to?(:sts_regional_endpoints) - sts_regional = cfg.sts_regional_endpoints - end - - Aws::Partitions::EndpointProvider.resolve( - cfg.region, - endpoint_prefix, - sts_regional, - { - dualstack: cfg.use_dualstack_endpoint, - fips: cfg.use_fips_endpoint - } - ) - end end end end diff --git a/gems/aws-sdk-core/spec/aws/endpoints_spec.rb b/gems/aws-sdk-core/spec/aws/endpoints_spec.rb index 87f6bb106f2..78e84edebe9 100644 --- a/gems/aws-sdk-core/spec/aws/endpoints_spec.rb +++ b/gems/aws-sdk-core/spec/aws/endpoints_spec.rb @@ -66,7 +66,7 @@ module Aws before do expect_any_instance_of(endpoints_service.const_get(:EndpointProvider)) - .to receive(:resolve_endpoint).and_return(endpoint) + .to receive(:resolve_endpoint).at_least(:once).and_return(endpoint) end describe '#resolve_auth_scheme' do