Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instance plugins #3051

Merged
merged 11 commits into from
Jun 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
describe 'Interfaces' do

before(:all) do
# TODO : support Aws.config[:sample] = { ... }
@tmpdir = SpecHelper.generate_service(['Sample'], multiple_files: true)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ module {{module_name}}
{{#client_constructor}}
# @overload initialize(options)
# @param [Hash] options
#
# @option options [Array<Seahorse::Client::Plugin>] :plugins ([]])
# A list of plugins to apply to the client. Each plugin is either a
# class name or an instance of a plugin class.
#
{{>documentation}}
{{/client_constructor}}
def initialize(*args)
Expand Down
4 changes: 2 additions & 2 deletions build_tools/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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.197.0"
MINIMUM_CORE_VERSION = "3.198.0"

# Minimum `aws-sdk-core` version for new S3 gem builds
MINIMUM_CORE_VERSION_S3 = "3.197.0"
MINIMUM_CORE_VERSION_S3 = "3.198.0"

EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration"

Expand Down
2 changes: 2 additions & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Support `:plugins` option on all Clients or using `Aws.config[:plugins]`.

3.197.2 (2024-06-20)
------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module Plugins
# @api private
class GlobalConfiguration < Seahorse::Client::Plugin

@identifiers = Set.new()
@identifiers = Set.new

# @api private
def before_initialize(client_class, options)
Expand All @@ -55,17 +55,18 @@ def before_initialize(client_class, options)
private

def apply_service_defaults(client_class, options)
if defaults = Aws.config[client_class.identifier]
defaults.each do |option_name, default|
options[option_name] = default unless options.key?(option_name)
end
return unless (defaults = Aws.config[client_class.identifier])

defaults.each do |option_name, default|
options[option_name] = default unless options.key?(option_name)
end
end

def apply_aws_defaults(client_class, options)
def apply_aws_defaults(_client_class, options)
Aws.config.each do |option_name, default|
next if self.class.identifiers.include?(option_name)
next if options.key?(option_name)

options[option_name] = default
end
end
Expand All @@ -80,9 +81,7 @@ def add_identifier(identifier)

# @return [Set<String>]
# @api private
def identifiers
@identifiers
end
attr_reader :identifiers

end
end
Expand Down
1 change: 0 additions & 1 deletion gems/aws-sdk-core/lib/aws-sdk-core/plugins/retry_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ class RetryErrors < Seahorse::Client::Plugin
functionality of `standard` mode along with automatic client side
throttling. This is a provisional mode that may change behavior
in the future.

DOCS
resolve_retry_mode(cfg)
end
Expand Down
24 changes: 17 additions & 7 deletions gems/aws-sdk-core/lib/seahorse/client/base.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require 'thread'

module Seahorse
module Client
class Base
Expand Down Expand Up @@ -60,6 +58,7 @@ def operation_names
def build_config(plugins, options)
config = Configuration.new
config.add_option(:api)
config.add_option(:plugins)
plugins.each do |plugin|
plugin.add_options(config) if plugin.respond_to?(:add_options)
end
Expand Down Expand Up @@ -96,9 +95,9 @@ def context_for(operation_name, params)
class << self

def new(options = {})
plugins = build_plugins
options = options.dup
before_initialize(plugins, options)
plugins = build_plugins(self.plugins + options.fetch(:plugins, []))
plugins = before_initialize(plugins, options)
client = allocate
client.send(:initialize, plugins, options)
client
Expand Down Expand Up @@ -209,17 +208,28 @@ def define_operation_methods
include(operations_module)
end

def build_plugins
def build_plugins(plugins)
plugins.map { |plugin| plugin.is_a?(Class) ? plugin.new : plugin }
end

def before_initialize(plugins, options)
plugins.each do |plugin|
plugin.before_initialize(self, options) if plugin.respond_to?(:before_initialize)
queue = Queue.new
plugins.each { |plugin| queue.push(plugin) }
until queue.empty?
plugin = queue.pop
next unless plugin.respond_to?(:before_initialize)

plugins_before = options.fetch(:plugins, [])
plugin.before_initialize(self, options)
plugins_after = build_plugins(options.fetch(:plugins, []) - plugins_before)
# Plugins with before_initialize can add other plugins
plugins_after.each { |p| queue.push(p); plugins << p }
end
plugins
end

def inherited(subclass)
super
subclass.instance_variable_set('@plugins', PluginList.new(@plugins))
end

Expand Down
1 change: 0 additions & 1 deletion gems/aws-sdk-core/lib/seahorse/client/plugins/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class Endpoint < Plugin
'http://example.com'
'https://example.com'
'http://example.com:123'

DOCS

def add_handlers(handlers, config)
Expand Down
54 changes: 52 additions & 2 deletions gems/aws-sdk-core/spec/aws/plugins/global_configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,23 @@ module Plugins
option(:property, 'plugin-default')
end)

let(:plugin) do
p = double('plugin')
allow(p).to receive(:is_a?).with(kind_of(Class)).and_return(false)
p
end

let(:options) do
{
region: 'us-east-1',
credentials: Credentials.new('akid', 'secret'),
plugins: [plugin]
}
end

before(:each) do
Aws.config.clear
Aws.config[:region] = 'us-east-1'
Aws.config[:credentials] = Credentials.new('akid', 'secret')
Aws.config = options
end

before(:all) do
Expand Down Expand Up @@ -45,6 +58,43 @@ module Plugins
expect(GlobalConfigClient.new(property: 'arg').config.property).to eq('arg')
end

context 'plugins' do
it 'instructs plugins to #before_initialize' do
expect(plugin).to receive(:before_initialize).with(GlobalConfigClient, options)
GlobalConfigClient.new
end

it 'instructs plugins to #add_options' do
expect(plugin).to receive(:add_options)
GlobalConfigClient.new
end

it 'instructs plugins to #add_handlers' do
expect(plugin).to receive(:add_handlers).
with(kind_of(Seahorse::Client::HandlerList), kind_of(Struct))
GlobalConfigClient.new
end

it 'instructs plugins to #after_initialize' do
expect(plugin).to receive(:after_initialize).with(kind_of(Seahorse::Client::Base))
GlobalConfigClient.new
end

it 'does not call methods that plugin does not respond to' do
plugin = Object.new
allow(plugin).to receive(:respond_to?).with(:before_initialize).and_return(false)
allow(plugin).to receive(:respond_to?).with(:add_options).and_return(false)
allow(plugin).to receive(:respond_to?).with(:add_handlers).and_return(false)
allow(plugin).to receive(:respond_to?).with(:after_initialize).and_return(false)
expect(plugin).not_to receive(:before_initialize)
expect(plugin).not_to receive(:add_options)
expect(plugin).not_to receive(:add_handlers)
expect(plugin).not_to receive(:after_initialize)
Aws.config[:plugins] = [plugin]
GlobalConfigClient.new
end
end

end
end
end
Loading
Loading