Skip to content

Commit de7a632

Browse files
committed
Add documentation for configuration options (and support for XML)
1 parent d7cce2b commit de7a632

File tree

10 files changed

+180
-76
lines changed

10 files changed

+180
-76
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ php:
66
- 7.0
77
- hhvm
88

9+
env:
10+
- AWS_BUNDLE_FORMAT_UNDER_TEST="yml"
11+
- AWS_BUNDLE_FORMAT_UNDER_TEST="php"
12+
- AWS_BUNDLE_FORMAT_UNDER_TEST="xml"
13+
914
sudo: false
1015

1116
install: travis_retry composer install --no-interaction --prefer-source

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ A Symfony bundle for including the [AWS SDK for PHP](https://github.com/aws/aws-
99

1010
## Installation
1111

12-
The AWS bundle can be installed via [Composer](http://getcomposer.org) by requiring the
13-
`aws/aws-sdk-php-symfony` package in your project's `composer.json`:
12+
The AWS bundle can be installed via [Composer](http://getcomposer.org) by
13+
requiring the`aws/aws-sdk-php-symfony` package in your project's `composer.json`:
1414

1515
```json
1616
{
@@ -37,6 +37,21 @@ class AppKernel extends Kernel
3737
}
3838
```
3939

40+
## Configuration
41+
42+
Configuration is handled by the SDK rather than by the bundle, and no validation
43+
is performed at compile time. Full documentation of the configuration options
44+
available can be read in the [SDK Guide](http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html).
45+
46+
To use a service for any configuration value, use `@` followed by the service
47+
name, such as `@a_service`. This syntax will be converted to a service during
48+
container compilation. If you want to use a string literal that begins with `@`,
49+
you will need to escape it by adding another `@` sign.
50+
51+
Sample configuration can be found in the `tests/fixtures` folder for [YAML](https://github.com/aws/aws-sdk-php-symfony/blob/master/tests/fixtures/config.yml), [PHP](https://github.com/aws/aws-sdk-php-symfony/blob/master/tests/fixtures/config.php), and [XML](https://github.com/aws/aws-sdk-php-symfony/blob/master/tests/fixtures/config.xml).
52+
53+
## Usage
54+
4055
This bundle exposes an instance of the `Aws\Sdk` object as well as instances of each AWS client object as services to your symfony application
4156

4257
<!-- BEGIN SERVICE TABLE -->
@@ -88,6 +103,7 @@ aws.sts | [Aws\Sts\StsClient](http://docs.aws.amazon.com/aws-sdk-php/v3/api/clas
88103
aws.support | [Aws\Support\SupportClient](http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Support.SupportClient.html)
89104
aws.swf | [Aws\Swf\SwfClient](http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Swf.SwfClient.html)
90105
aws.workspaces | [Aws\WorkSpaces\WorkSpacesClient](http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.WorkSpaces.WorkSpacesClient.html)
106+
aws_sdk | [Aws\Sdk](http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Sdk.html)
91107
<!-- END SERVICE TABLE -->
92108

93109
## Links

build/ReadMeUpdater.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ protected function getServicesTable()
7777
protected function getAWSServices(Container $container)
7878
{
7979
return array_filter($container->getServiceIds(), function ($service) {
80-
return strpos($service, 'aws.') === 0;
80+
return strpos($service, 'aws') === 0;
8181
});
8282
}
8383

src/DependencyInjection/AwsExtension.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Aws\Symfony\DependencyInjection;
44

5+
use Aws;
56
use Aws\AwsClient;
67
use Symfony\Component\Config\FileLocator;
78
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -22,12 +23,13 @@ public function load(array $configs, ContainerBuilder $container)
2223

2324
$configuration = new Configuration();
2425
$config = $this->processConfiguration($configuration, $configs);
26+
$this->inflateServicesInConfig($config);
2527

2628
$container
2729
->getDefinition('aws_sdk')
2830
->replaceArgument(0, $config);
2931

30-
foreach ($configuration->getAwsServices() as $awsService) {
32+
foreach (array_column(Aws\manifest(), 'namespace') as $awsService) {
3133
$container->setDefinition(
3234
'aws.' . strtolower($awsService),
3335
$this->createServiceDefinition($awsService)
@@ -36,7 +38,7 @@ public function load(array $configs, ContainerBuilder $container)
3638
}
3739

3840

39-
protected function createServiceDefinition($name)
41+
private function createServiceDefinition($name)
4042
{
4143
$clientClass = "Aws\\{$name}\\{$name}Client";
4244
$serviceDefinition = new Definition(
@@ -50,4 +52,23 @@ class_exists($clientClass) ? $clientClass : AwsClient::class
5052

5153
return $serviceDefinition;
5254
}
55+
56+
private function inflateServicesInConfig(array &$config)
57+
{
58+
array_walk($config, function (&$value) {
59+
if (is_array($value)) {
60+
$this->inflateServicesInConfig($value);
61+
}
62+
63+
if (is_string($value) && 0 === strpos($value, '@')) {
64+
// this is either a service reference or a string meant to
65+
// start with an '@' symbol. In any case, lop off the first '@'
66+
$value = substr($value, 1);
67+
if (0 !== strpos($value, '@')) {
68+
// this is a service reference, not a string literal
69+
$value = new Reference($value);
70+
}
71+
}
72+
});
73+
}
5374
}

src/DependencyInjection/Configuration.php

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,68 +15,8 @@ class Configuration implements ConfigurationInterface
1515
public function getConfigTreeBuilder()
1616
{
1717
$treeBuilder = new TreeBuilder;
18-
$rootNode = $treeBuilder->root('aws');
19-
20-
$childrenOfRoot = $rootNode->children();
21-
$this->addAwsConfigOptions($childrenOfRoot);
22-
23-
foreach ($this->getAwsServices() as $awsService) {
24-
$serviceConfig = $childrenOfRoot->arrayNode($awsService)->children();
25-
$this->addAwsConfigOptions($serviceConfig);
26-
$serviceConfig->end();
27-
}
28-
29-
$childrenOfRoot->end();
18+
$rootNode = $treeBuilder->root('aws', 'variable');
3019

3120
return $treeBuilder;
3221
}
33-
34-
public function getAwsServices()
35-
{
36-
return array_column(Aws\manifest(), 'namespace');
37-
}
38-
39-
40-
protected function addAwsConfigOptions(NodeBuilder $nodeBuilder)
41-
{
42-
$options = $this->getAwsConfigOptions();
43-
44-
$nodeTypeFilter = function ($type) {
45-
return function (array $option) use ($type) {
46-
return isset($option['valid']) &&
47-
1 === count($option['valid']) &&
48-
$type === $option['valid'][0];
49-
};
50-
};
51-
52-
foreach (['scalar' => 'string', 'integer' => 'int', 'boolean' => 'bool'] as $nodeType => $valueType) {
53-
foreach (array_filter($options, $nodeTypeFilter($valueType)) as $nodeName => $nodeManifest) {
54-
$nodeBuilder->node($nodeName, $nodeType)->end();
55-
56-
unset($options[$nodeName]);
57-
}
58-
}
59-
60-
foreach ($options as $nodeName => $nodeManifest) {
61-
$nodeBuilder->variableNode($nodeName)->end();
62-
}
63-
}
64-
65-
protected function getAwsConfigOptions()
66-
{
67-
static $args = [];
68-
69-
if (empty($args)) {
70-
$clientResolverClass = new ReflectionClass(ClientResolver::class);
71-
72-
$args = array_filter(
73-
$clientResolverClass->getStaticProperties()['defaultArgs'],
74-
function ($arg) {
75-
return empty($arg['internal']);
76-
}
77-
);
78-
}
79-
80-
return $args;
81-
}
8222
}

tests/DependencyInjection/AwsExtensionTest.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
use Aws\AwsClient;
77
use Aws\Sdk;
88
use ReflectionClass;
9+
use Symfony\Component\DependencyInjection\ContainerBuilder;
910
use Symfony\Component\DependencyInjection\ContainerInterface;
11+
use Symfony\Component\DependencyInjection\Reference;
1012

1113
class AwsExtensionTest extends \PHPUnit_Framework_TestCase
1214
{
@@ -17,7 +19,8 @@ class AwsExtensionTest extends \PHPUnit_Framework_TestCase
1719

1820
public function setUp()
1921
{
20-
$kernel = new AppKernel('test', true);
22+
$format = getenv('AWS_BUNDLE_FORMAT_UNDER_TEST') ?: 'yml';
23+
$kernel = new AppKernel('test', true, $format);
2124
$kernel->boot();
2225

2326
$this->container = $kernel->getContainer();
@@ -69,6 +72,47 @@ public function sdk_config_should_be_passed_directly_to_the_constructor_and_reso
6972
$this->assertSame($serviceRegion, $service->getRegion());
7073
}
7174

75+
/**
76+
* @test
77+
*/
78+
public function extension_should_escape_strings_that_begin_with_at_sign()
79+
{
80+
$extension = new AwsExtension;
81+
$config = ['credentials' => [
82+
'key' => '@@key',
83+
'secret' => '@@secret'
84+
]];
85+
$container = $this->getMock(ContainerBuilder::class, ['getDefinition', 'replaceArgument']);
86+
$container->expects($this->once())
87+
->method('getDefinition')
88+
->with('aws_sdk')
89+
->willReturnSelf();
90+
$container->expects($this->once())
91+
->method('replaceArgument')
92+
->with(0, ['credentials' => ['key' => '@key', 'secret' => '@secret']]);
93+
94+
$extension->load([$config], $container);
95+
}
96+
97+
/**
98+
* @test
99+
*/
100+
public function extension_should_expand_service_references()
101+
{
102+
$extension = new AwsExtension;
103+
$config = ['credentials' => '@aws_sdk'];
104+
$container = $this->getMock(ContainerBuilder::class, ['getDefinition', 'replaceArgument']);
105+
$container->expects($this->once())
106+
->method('getDefinition')
107+
->with('aws_sdk')
108+
->willReturnSelf();
109+
$container->expects($this->once())
110+
->method('replaceArgument')
111+
->with(0, ['credentials' => new Reference('aws_sdk')]);
112+
113+
$extension->load([$config], $container);
114+
}
115+
72116
public function serviceProvider()
73117
{
74118
$services = [];

tests/fixtures/AppKernel.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88

99
class AppKernel extends Kernel
1010
{
11+
private $extension;
12+
13+
public function __construct($env, $debug, $extension = 'yml')
14+
{
15+
$this->extension = $extension;
16+
parent::__construct($env, $debug);
17+
}
18+
1119
public function registerBundles()
1220
{
1321
return [
@@ -18,17 +26,17 @@ public function registerBundles()
1826

1927
public function registerContainerConfiguration(LoaderInterface $loader)
2028
{
21-
$loader->load($this->getTestConfigFile());
29+
$loader->load($this->getTestConfigFile($this->extension));
2230
}
2331

2432
public function getTestConfig()
2533
{
26-
return Yaml::parse(file_get_contents($this->getTestConfigFile()));
34+
return Yaml::parse(file_get_contents($this->getTestConfigFile('yml')));
2735
}
2836

2937

30-
protected function getTestConfigFile()
38+
private function getTestConfigFile($extension)
3139
{
32-
return __DIR__ . '/config.yml';
40+
return __DIR__ . '/config.' . $extension;
3341
}
3442
}

tests/fixtures/config.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Reference;
4+
5+
$container->loadFromExtension('framework', [
6+
'secret' => 'Rosebud was the name of his sled.',
7+
]);
8+
9+
$container->loadFromExtension('aws', [
10+
'version' => 'latest',
11+
'region' => 'us-east-1',
12+
'credentials' =>
13+
array (
14+
'key' => 'not-a-real-key',
15+
'secret' => '@@not-a-real-secret', // this will be escaped as '@not-a-real-secret'
16+
),
17+
'DynamoDb' =>
18+
array (
19+
'region' => 'us-west-2',
20+
),
21+
'S3' =>
22+
array (
23+
'version' => '2006-03-01',
24+
),
25+
'Sqs' =>
26+
array (
27+
'credentials' => new Reference('a_service'), // '@a_service' would also work in a PHP config
28+
),
29+
'CloudSearchDomain' =>
30+
array (
31+
'endpoint' => 'http://search-with-some-subdomain.us-east-1.cloudsearch.amazonaws.com',
32+
),
33+
]);
34+
35+
$container
36+
->register('a_service', 'Aws\\Credentials\\Credentials')
37+
->addArgument('a-different-fake-key')
38+
->addArgument('a-different-fake-secret');

tests/fixtures/config.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:framework="http://symfony.com/schema/dic/symfony"
4+
xmlns:aws="http://example.org/schema/dic/aws">
5+
6+
<framework:config secret="Rosebud was the name of his sled."/>
7+
8+
<aws:config version="latest" region="us-east-1">
9+
<aws:credentials
10+
key="not-a-real-key"
11+
secret="@@not-a-real-secret"
12+
/> <!-- secret will be escaped as '@not-a-real-secret '-->
13+
<aws:CloudSearchDomain
14+
endpoint="http://search-with-some-subdomain.us-east-1.cloudsearch.amazonaws.com"
15+
/>
16+
<aws:DynamoDb region="us-west-2"/>
17+
<aws:S3 version="2006-03-01"/>
18+
<aws:Sqs credentials="@a_service"/>
19+
</aws:config>
20+
21+
<services>
22+
<service id="a_service" class="Aws\Credentials\Credentials">
23+
<argument>a-different-fake-key</argument>
24+
<argument>a-different-fake-secret</argument>
25+
</service>
26+
</services>
27+
</container>

tests/fixtures/config.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ aws:
66
region: us-east-1
77
credentials:
88
key: not-a-real-key
9-
secret: not-a-real-secret
9+
secret: @@not-a-real-secret # this will be escaped as '@not-a-real-secret'
1010
DynamoDb:
1111
region: us-west-2
1212
S3:
1313
version: '2006-03-01'
1414
Sqs:
15-
credentials:
16-
key: a-different-fake-key
17-
secret: a-different-fake-secret
15+
credentials: @a_service
1816
CloudSearchDomain:
19-
endpoint: http://search-with-some-subdomain.us-east-1.cloudsearch.amazonaws.com
17+
endpoint: http://search-with-some-subdomain.us-east-1.cloudsearch.amazonaws.com
18+
19+
services:
20+
a_service:
21+
class: Aws\Credentials\Credentials
22+
arguments:
23+
- a-different-fake-key
24+
- a-different-fake-secret

0 commit comments

Comments
 (0)