8000 add optional config merging (#57) · stobrien89/symfony@0a66b85 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0a66b85

Browse files
authored
add optional config merging (symfony#57)
* add optional config merging * remove getRootNode for compatibility
1 parent fecf71d commit 0a66b85

File tree

3 files changed

+220
-5
lines changed

3 files changed

+220
-5
lines changed

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,15 @@ class AppKernel extends Kernel
3838

3939
## Configuration
4040

41-
Configuration is handled by the SDK rather than by the bundle, and no validation
42-
is performed at compile time. Full documentation of the configuration options
43-
available can be read in the [SDK Guide](http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html).
41+
By default, configuration is handled by the SDK rather than by the bundle, and
42+
no validation is performed at compile time. Full documentation of the
43+
configuration options available can be read in the [SDK Guide](http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html).
44+
45+
If AWS_MERGE_CONFIG environment variable is set to `true`, configuration
46+
validation and merging are enabled. The bundle validates and merges known
47+
configuration options, including for each service. Additional configuration
48+
options can be included in a single configuration file, but merging will fail
49+
if non-standard options are specified in more than once.
4450

4551
To use a service for any configuration value, use `@` followed by the service
4652
name, such as `@a_service`. This syntax will be converted to a service during

src/DependencyInjection/Configuration.php

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,105 @@ class Configuration implements ConfigurationInterface
1010
{
1111
public function getConfigTreeBuilder()
1212
{
13+
// Maintain backwars compatibility, only merge when AWS_MERGE_CONFIG is set
14+
$mergeConfig = getenv('AWS_MERGE_CONFIG') ?: false;
15+
$treeType = 'variable';
16+
17+
if ($mergeConfig) {
18+
$treeType = 'array';
19+
}
20+
1321
// Most recent versions of TreeBuilder have a constructor
1422
if (\method_exists(TreeBuilder::class, '__construct')) {
15-
$treeBuilder = new TreeBuilder('aws', 'variable');
23+
$treeBuilder = new TreeBuilder('aws', $treeType);
1624
} else { // which is not the case for older versions
1725
$treeBuilder = new TreeBuilder;
18-
$treeBuilder->root('aws', 'variable');
26+
$treeBuilder->root('aws', $treeType);
27+
}
28+
29+
// If not AWS_MERGE_CONFIG, return empty, variable TreeBuilder
30+
if (!$mergeConfig) {
31+
return $treeBuilder;
32+
}
33+
34+
$rootNode = $treeBuilder->root('aws');
35+
36+
// Define TreeBuilder to allow config validation and merging
37+
$rootNode
38+
->ignoreExtraKeys(false)
39+
->children()
40+
->variableNode('credentials')->end()
41+
->variableNode('debug')->end()
42+
->variableNode('stats')->end()
43+
->scalarNode('endpoint')->end()
44+
->variableNode('endpoint_discovery')->end()
45+
->arrayNode('http')
46+
->children()
47+
->floatNode('connect_timeout')->end()
48+
->booleanNode('debug')->end()
49+
->booleanNode('decode_content')->end()
50+
->integerNode('delay')->end()
51+
->variableNode('expect')->end()
52+
->variableNode('proxy')->end()
53+
->scalarNode('sink')->end()
54+
->booleanNode('synchronous')->end()
55+
->booleanNode('stream')->end()
56+
->floatNode('timeout')->end()
57+
->scalarNode('verify')->end()
58+
->end()
59+
->end()
60+
->scalarNode('profile')->end()
61+
->scalarNode('region')->end()
62+
->integerNode('retries')->end()
63+
->scalarNode('scheme')->end()
64+
->scalarNode('service')->end()
65+
->scalarNode('signature_version')->end()
66+
->variableNode('ua_append')->end()
67+
->variableNode('validate')->end()
68+
->scalarNode('version')->end()
69+
->end()
70+
;
71+
72+
//Setup config trees for each of the services
73+
foreach (array_column(Aws\manifest(), 'namespace') as $awsService) {
74+
$rootNode
75+
->children()
76+
->arrayNode($awsService)
77+
->ignoreExtraKeys(false)
78+
->children()
79+
->variableNode('credentials')->end()
80+
->variableNode('debug')->end()
81+
->variableNode('stats')->end()
82+
->scalarNode('endpoint')->end()
83+
->variableNode('endpoint_discovery')->end()
84+
->arrayNode('http')
85+
->children()
86+
->floatNode('connect_timeout')->end()
87+
->booleanNode('debug')->end()
88+
->booleanNode('decode_content')->end()
89+
->integerNode('delay')->end()
90+
->variableNode('expect')->end()
91+
->variableNode('proxy')->end()
92+
->scalarNode('sink')->end()
93+
->booleanNode('synchronous')->end()
94+
->booleanNode('stream')->end()
95+
->floatNode('timeout')->end()
96+
->scalarNode('verify')->end()
97+
->end()
98+
->end()
99+
->scalarNode('profile')->end()
100+
->scalarNode('region')->end()
101+
->integerNode('retries')->end()
102+
->scalarNode('scheme')->end()
103+
->scalarNode('service')->end()
104+
->scalarNode('signature_version')->end()
105+
->variableNode('ua_append')->end()
106+
->variableNode('validate')->end()
107+
->scalarNode('version')->end()
108+
->end()
109+
->end()
110+
->end()
111+
;
19112
}
20113

21114
return $treeBuilder;

tests/DependencyInjection/AwsExtensionTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,120 @@ public function extension_should_expand_service_references()
121121

122122
$extension->load([$config], $container);
123123
}
124+
125+
/**
126+
* @test
127+
*/
128+
public function extension_should_validate_and_merge_configs()
129+
{
130+
putenv('AWS_MERGE_CONFIG=true');
131+
$extension = new AwsExtension;
132+
$config = [
133+
'credentials' => false,
134+
'debug' => [
135+
'http' => true
136+
],
137+
'stats' => [
138+
'http' => true
139+
],
140+
'retries' => 5,
141+
'endpoint' => 'http://localhost:8000',
142+
'endpoint_discovery' => [
143+
'enabled' => true,
144+
'cache_limit' => 1000
145+
],
146+
'http' => [
147+
'connect_timeout' => 5.5,
148+
'debug' => true,
149+
'decode_content' => true,
150+
'delay' => 1,
151+
'expect' => true,
152+
'proxy' => 'http://localhost:9000',
153+
'sink' => '/path/to/sink',
154+
'synchronous' => true,
155+
'stream' => true,
156+
'timeout' => 3.14,
157+
'verify' => '/path/to/ca_cert_bundle'
158+
],
159+
'profile' => 'prod',
160+
'region' => 'us-west-2',
161+
'retries' => 5,
162+
'scheme' => 'http',
163+
'signature_version' => 'v4',
164+
'ua_append' => [
165+
'prod',
166+
'foo'
167+
],
168+
'validate' => [
169+
'required' => true
170+
],
171+
'version' => 'latest',
172+
'S3' => [
173+
'version' => '2006-03-01',
174+
]
175+
];
176+
$configDev = [
177+
'credentials' => '@aws_sdk',
178+
'debug' => true,
179+
'stats' => true,
180+
'ua_append' => 'dev',
181+
'validate' => true,
182+
];
183+
$container = $this->getMockBuilder(ContainerBuilder::class)
184+
->setMethods(['getDefinition', 'replaceArgument'])
185+
->getMock();
186+
$container->expects($this->once())
187+
->method('getDefinition')
188+
->with('aws_sdk')
189+
->willReturnSelf();
190+
$container->expects($this->once())
191+
->method('replaceArgument')
192+
->with(0, $this->callback(function ($arg) {
193+
return is_array($arg)
194+
&& isset($arg['credentials'])
195+
&& $arg['credentials'] instanceof Reference
196+
&& (string) $arg['credentials'] === 'aws_sdk'
197+
&& isset($arg['debug'])
198+
&& (bool) $arg['debug'] === true
199+
&& isset($arg['stats'])
200+
&& (bool) $arg['stats'] === true
201+
&& isset($arg['retries'])
202+
&& (integer) $arg['retries'] === 5
203+
&& isset($arg['endpoint'])
204+
&& (string) $arg['endpoint'] === 'http://localhost:8000'
205+
&& isset($arg['validate'])
206+
&& (bool) $arg['validate'] === true
207+
&& isset($arg['endpoint_discovery']['enabled'])
208+
&& isset($arg['endpoint_discovery']['cache_limit'])
209+
&& (bool) $arg['endpoint_discovery']['enabled'] === true
210+
&& (integer) $arg['endpoint_discovery']['cache_limit'] === 1000
211+
&& isset($arg['S3']['version'])
212+
&& (string) $arg['S3']['version'] === '2006-03-01'
213+
;
214+
}));
215+
216+
$extension->load([$config, $configDev], $container);
217+
}
218+
219+
/**
220+
* @test
221+
*
222+
* @expectedException RuntimeException
223+
*/
224+
public function extension_should_error_merging_unknown_config_options()
225+
{
226+
putenv('AWS_MERGE_CONFIG=true');
227+
$extension = new AwsExtension;
228+
$config = [
229+
'foo' => 'bar'
230+
];
231+
$configDev = [
232+
'foo' => 'baz'
233+
];
234+
$container = $this->getMockBuilder(ContainerBuilder::class)
235+
->setMethods(['getDefinition', 'replaceArgument'])
236+
->getMock();
237+
238+
$extension->load([$config, $configDev], $container);
239+
}
124240
}

0 commit comments

Comments
 (0)
0