8000 feature #27157 [DI] Select specific key from an array resolved env va… · symfony/symfony@eceabee · GitHub
[go: up one dir, main page]

Skip to content

Commit eceabee

Browse files
feature #27157 [DI] Select specific key from an array resolved env var (bobvandevijver)
This PR was squashed before being merged into the 4.2-dev branch (closes #27157). Discussion ---------- [DI] Select specific key from an array resolved env var | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes <!-- don't forget to update src/**/CHANGELOG.md files --> | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | Discussed in #25643 <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | symfony/symfony-docs#9734 <!-- required for new features --> <!-- Write a short README entry for your feature/bugfix here (replace this comment block.) This will help people understand your PR and can be used as a start of the Doc PR. Additionally: - Bug fixes must be submitted against the lowest branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against the master branch. --> As discussed in #25643, it would be convenient to have an key processor for environment variables which have been read from for example a JSON file. The main advantage of this feature lies in specifying a single file for your secrets, that can be directly used in your configuration, without leaking them into your env. ## Example **.secrets.json** ```json { "database_password": "xxx" } ``` **.env** ```env APP_SECRETS=/opt/application/.secrets.json DATABASE_URL=mysql://myuser:%database_password%@localhost:3306/mydb ``` **services.yaml** ```yaml parameters: database_password: '%env(key:database_password:json:file:APP_SECRETS)%' ``` This example configuration will result in a `database_password` parameter being filled with `xxx`, and due to Doctrine defaults, the database url will be resolved with the correct password. Commits ------- 42186a2 [DI] Select specific key from an array resolved env var
2 parents f827fec + 42186a2 commit eceabee

File tree

3 files changed

+127
-0
lines changed

3 files changed

+127
-0
lines changed

src/Symfony/Component/DependencyInjection/EnvVarProcessor.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public static function getProvidedTypes()
4141
'float' => 'float',
4242
'int' => 'int',
4343
'json' => 'array',
44+
'key' => 'bool|int|float|string|array',
4445
'resolve' => 'string',
4546
'string' => 'string',
4647
);
@@ -53,6 +54,25 @@ public function getEnv($prefix, $name, \Closure $getEnv)
5354
{
5455
$i = strpos($name, ':');
5556

57+
if ('key' === $prefix) {
58+
if (false === $i) {
59+
throw new RuntimeException(sprintf('Invalid configuration: env var "key:%s" does not contain a key specifier.', $name));
60+
}
61+
62+
$next = substr($name, $i + 1);
63+
$key = substr($name, 0, $i);
64+
$array = $getEnv($next);
65+
66+
if (!is_array($array)) {
67+
throw new RuntimeException(sprintf('Resolved value of "%s" did not result in an array value.', $next));
68+
}
69+
if (!array_key_exists($key, $array)) {
70+
throw new RuntimeException(sprintf('Key "%s" not found in "%s" (resolved from "%s")', $key, json_encode($array), $next));
71+
}
72+
73+
return $array[$key];
74+
}
75+
5676
if ('file' === $prefix) {
5777
if (!is_scalar($file = $getEnv($name))) {
5878
throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name));

src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function testSimpleProcessor()
3838
'float' => array('float'),
3939
'int' => array('int'),
4040
'json' => array('array'),
41+
'key' => array('bool', 'int', 'float', 'string', 'array'),
4142
'resolve' => array('string'),
4243
'string' => array('string'),
4344
);

src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,110 @@ public function testGetEnvUnknown()
314314
return 'foo';
315315
});
316316
}
317+
318+
/**
319+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
320+
* @expectedExceptionMessage Invalid configuration: env var "key:foo" does not contain a key specifier.
321+
*/
322+
public function testGetEnvKeyInvalidKey()
323+
{
324+
$processor = new EnvVarProcessor(new Container());
325+
326+
$processor->getEnv('key', 'foo', function ($name) {
327+
$this->fail('Should not get here');
328+
});
329+
}
330+
331+
/**
332+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
333+
* @expectedExceptionMessage Resolved value of "foo" did not result in an array value.
334+
* @dataProvider noArrayValues
335+
*/
336+
public function testGetEnvKeyNoArrayResult($value)
337+
{
338+
$processor = new EnvVarProcessor(new Container());
339+
340+
$processor->getEnv('key', 'index:foo', function ($name) use ($value) {
341+
$this->assertSame('foo', $name);
342+
343+
return $value;
344+
});
345+
}
346+
347+
public function noArrayValues()
348+
{
349+
return array(
350+
array(null),
351+
array('string'),
352+
array(1),
353+
array(true),
354+
);
355+
}
356+
357+
/**
358+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
359+
* @expectedExceptionMessage Key "index" not found in
360+
* @dataProvider invalidArrayValues
361+
*/
362+
public function testGetEnvKeyArrayKeyNotFound($value)
363+
{
364+
$processor = new EnvVarProcessor(new Container());
365+
366+
$processor->getEnv('key', 'index:foo', function ($name) use ($value) {
367+
$this->assertSame('foo', $name);
368+
369+
return $value;
370+
});
371+
}
372+
373+
public function invalidArrayValues()
374+
{
375+
return array(
376+
array(array()),
377+
array(array('index2' => 'value')),
378+
array(array('index', 'index2')),
379+
);
380+
}
381+
382+
/**
383+
* @dataProvider arrayValues
384+
*/
385+
public function testGetEnvKey($value)
386+
{
387+
$processor = new EnvVarProcessor(new Container());
388+
389+
$this->assertSame($value['index'], $processor->getEnv('key', 'index:foo', function ($name) use ($value) {
390+
$this->assertSame('foo', $name);
391+
392+
return $value;
393+
}));
394+
}
395+
396+
public function arrayValues()
397+
{
398+
return array(
399+
array(array('index' => 'password')),
400+
array(array('index' => 'true')),
401+
array(array('index' => false)),
402+
array(array('index' => '1')),
403+
array(array('index' => 1)),
404+
array(array('index' => '1.1')),
405+
array(array('index' => 1.1)),
406+
array(array('index' => array())),
407+
array(array('index' => array('val1', 'val2'))),
408+
);
409+
}
410+
411+
public function testGetEnvKeyChained()
412+
{
413+
$processor = new EnvVarProcessor(new Container());
414+
415+
$this->assertSame('password', $processor->getEnv('key', 'index:file:foo', function ($name) {
416+
$this->assertSame('file:foo', $name);
417+
418+
return array(
419+
'index' => 'password',
420+
);
421+
}));
422+
}
317423
}

0 commit comments

Comments
 (0)
0