From 9022e0cb1a49599d86fecaf2c10d314e352a7609 Mon Sep 17 00:00:00 2001 From: Vlad Gorenkin Date: Tue, 9 Oct 2018 19:14:25 +0600 Subject: [PATCH 1/2] #30 Add functionality to set up multiple AWS SDK instances --- src/AwsBundle/Client/AwsSdks.php | 30 +++++++++++++ .../DependencyInjection/Configuration.php | 43 +++++++++++++++++-- .../RuworkAwsExtension.php | 41 +++++++++++++++--- src/AwsBundle/Resources/config/services.php | 5 +++ .../DependencyInjection/ConfigurationTest.php | 35 +++++++++++---- 5 files changed, 135 insertions(+), 19 deletions(-) create mode 100644 src/AwsBundle/Client/AwsSdks.php diff --git a/src/AwsBundle/Client/AwsSdks.php b/src/AwsBundle/Client/AwsSdks.php new file mode 100644 index 0000000..d026f1f --- /dev/null +++ b/src/AwsBundle/Client/AwsSdks.php @@ -0,0 +1,30 @@ +locator = $locator; + $this->defaultName = $defaultName; + } + + public function has(string $name): bool + { + return $this->locator->has($name); + } + + public function get(?string $name = null): Sdk + { + return $this->locator->get($name ?? $this->defaultName); + } +} diff --git a/src/AwsBundle/DependencyInjection/Configuration.php b/src/AwsBundle/DependencyInjection/Configuration.php index 2ccb3ef..3b85573 100644 --- a/src/AwsBundle/DependencyInjection/Configuration.php +++ b/src/AwsBundle/DependencyInjection/Configuration.php @@ -19,13 +19,48 @@ public function getConfigTreeBuilder() // @formatter:off return (new TreeBuilder()) ->root('ruwork_aws') + ->beforeNormalization() + ->ifTrue(function ($value): bool { + return \is_array($value) && [] !== $value && !\array_key_exists('sdks', $value); + }) + ->then(function (array $value): array { + return [ + 'sdks' => [ + 'default' => $value, + ], + 'default_sdk' => 'default', + ]; + }) + ->end() ->children() - ->scalarNode('http_handler') - ->defaultValue(\interface_exists(HttpClient::class) ? HttplugHandler::class : null) + ->arrayNode('sdks') + ->isRequired() + ->arrayPrototype() + ->children() + ->scalarNode('http_handler') + ->defaultValue(\interface_exists(HttpClient::class) ? HttplugHandler::class : null) + ->end() + ->end() + ->ignoreExtraKeys(false) + ->end() + ->end() + ->scalarNode('default_sdk') + ->isRequired() + ->cannotBeEmpty() ->end() ->end() - ->ignoreExtraKeys(false) - ->end(); + ->validate() + ->ifTrue(function ($value): bool { + return \is_array($value) + && isset($value['default_sdk']) + && isset($value['sdks']) + && !isset($value['sdks'][$value['default_sdk']]); + }) + ->then(function (array $value): void { + throw new \InvalidArgumentException(\sprintf('SDK "%s" is not defined and cannot be used as default.', $value['default_sdk'])); + }) + ->end() + ->end(); // @formatter:on } } diff --git a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php index c03fd0d..d480de9 100644 --- a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php +++ b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php @@ -6,9 +6,13 @@ use Aws\Sdk; use Http\Client\HttpClient; +use Ruwork\AwsBundle\Client\AwsSdks; use Ruwork\AwsBundle\HttpHandler\HttplugHandler; use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension; @@ -24,16 +28,41 @@ public function loadInternal(array $config, ContainerBuilder $container): void $loader = new PhpFileLoader($container, $locator); $loader->load('services.php'); - if (isset($config['http_handler'])) { - $config['http_handler'] = new Reference($config['http_handler']); - } + if (\class_exists(Sdk::class)) { + $references = []; + foreach ($config['sdks'] as $name => $value) { + if (isset($value['http_handler'])) { + $value['http_handler'] = new Reference($value['http_handler']); + } + $references[$name] = $this->registerSdk($container, $name, $value); + } - $container - ->findDefinition(Sdk::class) - ->setArgument(0, $config); + $sdkAlias = new Alias('ruwork_aws.sdk.'.$config['default_sdk'], false); + $container->setAlias(Sdk::class, $sdkAlias); + $container->setAlias('ruwork_aws.sdk._default', $sdkAlias); + + $container + ->findDefinition(AwsSdks::class) + ->setArguments([ + '$locator' => ServiceLocatorTagPass::register($container, $references), + '$defaultName' => $config['default_sdk'], + ]); + } if (!\interface_exists(HttpClient::class)) { $container->removeDefinition(HttplugHandler::class); } } + + public function registerSdk(ContainerBuilder $container, string $name, array $config): Reference + { + $id = 'ruwork_aws.sdk.'.$name; + + $container + ->setDefinition($id, new Definition(Sdk::class)) + ->setPublic(false) + ->setArgument(0, $config); + + return new Reference($id); + } } diff --git a/src/AwsBundle/Resources/config/services.php b/src/AwsBundle/Resources/config/services.php index 0d4c479..0a88f5b 100644 --- a/src/AwsBundle/Resources/config/services.php +++ b/src/AwsBundle/Resources/config/services.php @@ -6,6 +6,7 @@ use Aws\Sdk; use Aws\Ses\SesClient; +use Ruwork\AwsBundle\Client\AwsSdks; use Ruwork\AwsBundle\HttpHandler\HttplugHandler; return function (ContainerConfigurator $container): void { @@ -23,6 +24,10 @@ ->set(SesClient::class) ->factory([ref(Sdk::class), 'createSes']); + // Sdks + + $services->set(AwsSdks::class); + // HttpHandler $services diff --git a/tests/AwsBundle/DependencyInjection/ConfigurationTest.php b/tests/AwsBundle/DependencyInjection/ConfigurationTest.php index 1189005..7d7c967 100644 --- a/tests/AwsBundle/DependencyInjection/ConfigurationTest.php +++ b/tests/AwsBundle/DependencyInjection/ConfigurationTest.php @@ -15,24 +15,41 @@ class ConfigurationTest extends TestCase { use ConfigurationTestCaseTrait; - public function testDefault(): void + public function testDefaults(): void { - $this->assertProcessedConfigurationEquals([], [ - 'http_handler' => HttplugHandler::class, - ]); + $this->assertProcessedConfigurationEquals( + [ + 'sdks' => [ + 'extra_value' => 'value', + ], + ], + [ + 'sdks' => [ + 'default' => [ + 'http_handler' => HttplugHandler::class, + 'extra_value' => 'value', + ], + ], + 'default_sdk' => 'default', + ] + ); } - public function testExtraValues(): void + public function testSingleSdkExpanding(): void { $this->assertProcessedConfigurationEquals( [ - [ - 'extra' => 'value', + 'sdks' => [ + 'http_handler' => HttplugHandler::class, ], ], [ - 'extra' => 'value', - 'http_handler' => HttplugHandler::class, + 'sdks' => [ + 'default' => [ + 'http_handler' => HttplugHandler::class, + ], + ], + 'default_sdk' => 'default', ] ); } From 28487d97a0da8c48279ebe3e75f0b747f2f7cedf Mon Sep 17 00:00:00 2001 From: Vlad Gorenkin Date: Mon, 15 Oct 2018 13:50:43 +0600 Subject: [PATCH 2/2] #30 Use container inside AwsSdks instead of locator --- src/AwsBundle/Client/AwsSdks.php | 12 ++++++------ .../DependencyInjection/RuworkAwsExtension.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/AwsBundle/Client/AwsSdks.php b/src/AwsBundle/Client/AwsSdks.php index d026f1f..80665a9 100644 --- a/src/AwsBundle/Client/AwsSdks.php +++ b/src/AwsBundle/Client/AwsSdks.php @@ -5,26 +5,26 @@ namespace Ruwork\AwsBundle\Client; use Aws\Sdk; -use Symfony\Component\DependencyInjection\ServiceLocator; +use Psr\Container\ContainerInterface; final class AwsSdks { - private $locator; + private $container; private $defaultName; - public function __construct(ServiceLocator $locator, string $defaultName) + public function __construct(ContainerInterface $container, string $defaultName) { - $this->locator = $locator; + $this->container = $container; $this->defaultName = $defaultName; } public function has(string $name): bool { - return $this->locator->has($name); + return $this->container->has($name); } public function get(?string $name = null): Sdk { - return $this->locator->get($name ?? $this->defaultName); + return $this->container->get($name ?? $this->defaultName); } } diff --git a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php index d480de9..5254cb2 100644 --- a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php +++ b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php @@ -44,7 +44,7 @@ public function loadInternal(array $config, ContainerBuilder $container): void $container ->findDefinition(AwsSdks::class) ->setArguments([ - '$locator' => ServiceLocatorTagPass::register($container, $references), + '$container' => ServiceLocatorTagPass::register($container, $references), '$defaultName' => $config['default_sdk'], ]); }