From 2e872331e7980316d92233c5ee42321d6a5b34e7 Mon Sep 17 00:00:00 2001 From: Yenfry Herrera Feliz Date: Tue, 26 Nov 2024 10:32:32 -0800 Subject: [PATCH] feat: add generic method for config resolution Resolve config default values that uses just the ConfigurationResolver::resolve method, from just a single method. This avoids the overhead of having layers of methods for just consuming `ConfigurationResolver::resolve`, and instead this one will be called directly. --- src/ClientResolver.php | 101 +++++++++++---------- tests/ClientResolverTest.php | 165 ++++++++++------------------------- 2 files changed, 103 insertions(+), 163 deletions(-) diff --git a/src/ClientResolver.php b/src/ClientResolver.php index c752377d58..fd77ae96c9 100644 --- a/src/ClientResolver.php +++ b/src/ClientResolver.php @@ -47,6 +47,20 @@ class ClientResolver /** @var array */ private $argDefinitions; + /** + * When using this option as default please make sure that, your config + * has at least one data type defined in `valid` otherwise it will be + * defaulted to `string`. Also, the default value will be the falsy value + * based on the resolved data type. For example, the default for `string` + * will be `''` and for bool will be `false`. + * + * @var string + */ + const DEFAULT_FROM_ENV_INI = [ + __CLASS__, + '_resolve_from_env_ini' + ]; + /** @var array Map of types to a corresponding function */ private static $typeMap = [ 'resource' => 'is_resource', @@ -91,7 +105,7 @@ class ClientResolver 'valid' => ['bool'], 'doc' => 'Set to true to disable endpoint urls configured using `AWS_ENDPOINT_URL` and `endpoint_url` shared config option.', 'fn' => [__CLASS__, '_apply_ignore_configured_endpoint_urls'], - 'default' => [__CLASS__, '_default_ignore_configured_endpoint_urls'], + 'default' => self::DEFAULT_FROM_ENV_INI, ], 'endpoint' => [ 'type' => 'value', @@ -105,7 +119,7 @@ class ClientResolver 'valid' => ['string'], 'doc' => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.', 'fn' => [__CLASS__, '_apply_region'], - 'default' => [__CLASS__, '_default_region'] + 'default' => self::DEFAULT_FROM_ENV_INI ], 'version' => [ 'type' => 'value', @@ -244,7 +258,7 @@ class ClientResolver 'valid' => ['bool', 'callable'], 'doc' => 'Set to true to disable request compression for supported operations', 'fn' => [__CLASS__, '_apply_disable_request_compression'], - 'default' => [__CLASS__, '_default_disable_request_compression'], + 'default' => self::DEFAULT_FROM_ENV_INI, ], 'request_min_compression_size_bytes' => [ 'type' => 'value', @@ -327,7 +341,7 @@ class ClientResolver 'valid' => ['array', 'string'], 'doc' => 'A comma-delimited list of supported regions sent in sigv4a requests.', 'fn' => [__CLASS__, '_apply_sigv4a_signing_region_set'], - 'default' => [__CLASS__, '_default_sigv4a_signing_region_set'] + 'default' => self::DEFAULT_FROM_ENV_INI ] ]; @@ -397,7 +411,15 @@ public function resolve(array $args, HandlerList $list) || $a['default'] instanceof \Closure ) ) { - $args[$key] = $a['default']($args); + if ($a['default'] === self::DEFAULT_FROM_ENV_INI) { + $args[$key] = $a['default']( + $key, + $a['valid'][0] ?? 'string', + $args + ); + } else { + $args[$key] = $a['default']($args); + } } else { $args[$key] = $a['default']; } @@ -590,15 +612,6 @@ public static function _apply_disable_request_compression($value, array &$args) $args['config']['disable_request_compression'] = $value; } - public static function _default_disable_request_compression(array &$args) { - return ConfigurationResolver::resolve( - 'disable_request_compression', - false, - 'bool', - $args - ); - } - public static function _apply_min_compression_size($value, array &$args) { if (is_callable($value)) { $value = $value(); @@ -1259,16 +1272,6 @@ public static function _apply_suppress_php_deprecation_warning($value, &$args) } } - public static function _default_ignore_configured_endpoint_urls(array &$args) - { - return ConfigurationResolver::resolve( - 'ignore_configured_endpoint_urls', - false, - 'bool', - $args - ); - } - public static function _default_endpoint(array &$args) { if ($args['config']['ignore_configured_endpoint_urls'] @@ -1318,16 +1321,6 @@ public static function _apply_sigv4a_signing_region_set($value, array &$args) } } - public static function _default_sigv4a_signing_region_set(array $args) - { - return ConfigurationResolver::resolve( - 'sigv4a_signing_region_set', - '', - 'string', - $args - ); - } - public static function _apply_region($value, array &$args) { if (empty($value)) { @@ -1336,16 +1329,6 @@ public static function _apply_region($value, array &$args) $args['region'] = $value; } - public static function _default_region($args) - { - return ConfigurationResolver::resolve( - 'region', - '', - 'string', - $args - ); - } - public static function _missing_region(array $args) { $service = $args['service'] ?? ''; @@ -1362,6 +1345,36 @@ public static function _missing_region(array $args) throw new IAE($msg); } + /** + * Resolves a value from env or config. + * + * @param $key + * @param $expectedType + * @param $args + * + * @return mixed|string + */ + private static function _resolve_from_env_ini( + $key, + $expectedType, + $args + ) { + static $typeDefaultMap = [ + 'int' => 0, + 'bool' => false, + 'boolean' => false, + 'string' => '', + 'array' => [] + ]; + + return ConfigurationResolver::resolve( + $key, + $typeDefaultMap[$expectedType] ?? '', + $expectedType, + $args + ); + } + /** * Extracts client options for the endpoint provider to its own array * diff --git a/tests/ClientResolverTest.php b/tests/ClientResolverTest.php index 74abac2fe8..956b61b7de 100644 --- a/tests/ClientResolverTest.php +++ b/tests/ClientResolverTest.php @@ -1701,23 +1701,13 @@ public function testEmitsDeprecationWarning() * Tests the flag `use_aws_shared_config_files` is applied to the method * for resolving a default value for a config. * - * @param $resolverDefinition - * @param $args - * @param $expected - * - * @dataProvider methodAppliesUserAwsSharedFilesProvider - * * @return void */ - public function testMethodAppliesUseAwsSharedFiles( - $resolverDefinition, - $args, - $expected - ): void + public function testResolveFromEnvIniUseAwsSharedFiles(): void { // The config being tested - $configKey = array_key_first($resolverDefinition); - $configValue = $expected ?? 'foo_value'; + $configKey = 'foo-config-key'; + $configValue = 'foo-config-value'; // Populate config file $tempDir = sys_get_temp_dir(); $awsDir = $tempDir . "/.aws"; @@ -1734,12 +1724,49 @@ public function testMethodAppliesUseAwsSharedFiles( putenv(ConfigurationResolver::ENV_CONFIG_FILE . "=" . $configFile); try { - $resolver = new ClientResolver($resolverDefinition); - $resolvedArgs = $resolver->resolve($args, new HandlerList()); - if ($expected) { - $this->assertEquals($expected, $resolvedArgs[$configKey]); - } else { - $this->assertNull($resolvedArgs[$configKey]); + $resolver = new ClientResolver([ + $configKey => [ + 'type' => 'value', + 'valid' => ['string'], + 'fn' => function ($value, array &$args) use ($configKey) { + if (empty($value)) { + $args[$configKey] = null; + + return; + } + + $args[$configKey] = $value; + }, + 'default' => ClientResolver::DEFAULT_FROM_ENV_INI + ] + ]); + $testCases = [ + [ + 'args' => [ + 'use_aws_shared_config_files' => true + ], + 'expected' => $configValue + ], + [ + 'args' => [ + 'use_aws_shared_config_files' => false + ], + 'expected' => null + ] + ]; + foreach ($testCases as $case) { + $resolvedArgs = $resolver->resolve( + $case['args'], + new HandlerList() + ); + if ($case['expected']) { + $this->assertEquals( + $case['expected'], + $resolvedArgs[$configKey] + ); + } else { + $this->assertNull($resolvedArgs[$configKey]); + } } } finally { unlink($configFile); @@ -1755,104 +1782,4 @@ public function testMethodAppliesUseAwsSharedFiles( } } } - - /** - * @return array[] - */ - public function methodAppliesUserAwsSharedFilesProvider(): array - { - // We use a custom apply function to prevent validation - // errors, since every apply method may have a - // different validation logic. - $customApplyFn = function ($config) { - return static function ($value, array &$args) use ($config) { - if (empty($value)) { - $args[$config] = null; - - return; - } - - $args[$config] = $value; - }; - }; - - return [ - 'resolve_region_from_config' => [ - 'resolver_definition' => [ - 'region' => [ - 'type' => 'value', - 'valid' => ['string'], - 'fn' => $customApplyFn( - 'region' - ), - 'default' => [ - ClientResolver::class, - '_default_region' - ] - ] - ], - 'args' => [ - 'use_aws_shared_config_files' => true, - ], - 'expected' => 'foo-region' - ], - 'not_resolve_region_from_config' => [ - 'resolver_definition' => [ - 'region' => [ - 'type' => 'value', - 'valid' => ['string'], - 'fn' => $customApplyFn( - 'region' - ), - 'default' => [ - ClientResolver::class, - '_default_region' - ] - ] - ], - 'args' => [ - 'use_aws_shared_config_files' => false, - ], - 'expected' => null - ], - 'resolve_sigv4a_signing_region_set_from_config' => [ - 'resolver_definition' => [ - 'sigv4a_signing_region_set' => [ - 'type' => 'value', - 'valid' => ['string'], - 'fn' => $customApplyFn( - 'sigv4a_signing_region_set' - ), - 'default' => [ - ClientResolver::class, - '_default_sigv4a_signing_region_set' - ] - ] - ], - 'args' => [ - 'use_aws_shared_config_files' => true, - ], - 'expected' => 'foo-region' - ], - 'not_resolve_sigv4a_signing_region_set_from_config' => [ - 'resolver_definition' => [ - 'sigv4a_signing_region_set' => [ - 'type' => 'value', - 'valid' => ['string'], - 'fn' => $customApplyFn( - 'sigv4a_signing_region_set' - ), - 'default' => [ - ClientResolver::class, - '_default_sigv4a_signing_region_set' - ] - ] - ], - 'args' => [ - 'use_aws_shared_config_files' => false, - ], - 'expected' => null - ] - ]; - } }