Skip to content

Commit

Permalink
Closes aws#1239 -- Added support to configure client endpoints throug…
Browse files Browse the repository at this point in the history
…h environment variables
  • Loading branch information
bradynpoulsen committed Apr 5, 2017
1 parent c5d85fb commit 70f9e7f
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/ClientResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
*/
class ClientResolver
{
const ENV_FORMAT_REGION_SERVICE = 'AWS_%s_%s_ENDPOINT';
const ENV_FORMAT_SERVICE = 'AWS_%s_ENDPOINT';

/** @var array */
private $argDefinitions;

Expand Down Expand Up @@ -435,6 +438,25 @@ public static function _apply_api_provider(callable $value, array &$args)
public static function _apply_endpoint_provider(callable $value, array &$args)
{
if (!isset($args['endpoint'])) {
$regionEnvName = build_env_name(self::ENV_FORMAT_REGION_SERVICE, $args['region'], $args['service']);
$serviceEnvName = build_env_name(self::ENV_FORMAT_SERVICE, $args['service']);

/**
* Search for an environment variable endpoint configuration with this priority:
* - AWS_<region>_<service>_ENDPOINT
* - AWS_<service>_ENDPOINT
*
* Future development consideration should be made with getenv's $local_only optional to ensure
* environment variables are configurable using putenv in FastCGI environments
* @see http://php.net/manual/function.getenv.php#refsect1-function.getenv-notes getenv FastCGI Note
*/
$envValue = getenv($regionEnvName)
?: getenv($serviceEnvName);
if ($envValue) {
$args['endpoint'] = $envValue;
return;
}

$endpointPrefix = isset($args['api']['metadata']['endpointPrefix'])
? $args['api']['metadata']['endpointPrefix']
: $args['service'];
Expand Down
30 changes: 30 additions & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,33 @@ function manifest($service = null)
);
}
}


/**
* Build the environment variable name from a formatted string using UPPER_CAMEL_CASE
* Note: parameters will be prepared using the prepare_env_name() function
* @see http://php.net/manual/function.sprintf.php
*
* @param string $format The formatted string used as the template
* @param string ...$values Values to be used
* @return string Returns the formatted environment variable name
*/
function build_env_name()
{
$values = func_get_args();
$format = array_shift($values);

$prepared = array_map('\Aws\prepare_env_name', $values);
return call_user_func_array('sprintf', array_merge([$format], $prepared));
}

/**
* Converts a string to all caps and replaces hyphens (-) with underscores (_) to produce UPPER_CAMEL_CASE
*
* @param string $source
* @return string
*/
function prepare_env_name($source)
{
return str_replace('-', '_', strtoupper($source));
}
52 changes: 52 additions & 0 deletions tests/ClientResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
namespace Aws\Test;

use Aws\Api\Service;
use function Aws\build_env_name;
use Aws\ClientResolver;
use Aws\CommandInterface;
use Aws\Credentials\CredentialProvider;
use Aws\Credentials\Credentials;
use Aws\DynamoDb\DynamoDbClient;
use Aws\Endpoint\Partition;
use Aws\Endpoint\PartitionInterface;
use Aws\LruArrayCache;
use Aws\S3\S3Client;
use Aws\HandlerList;
Expand Down Expand Up @@ -644,6 +646,56 @@ public function endpointProviderReturnProvider()
];
}

/**
* @dataProvider endpointValueConfiguredInEnvironmentVariableProvider
*
* @param string $service
* @param string $region
* @param string $envName
* @param string $envValue
*/
public function testResolvesEndpointValueConfiguredInEnvironmentVariable(
$service,
$region,
$envName,
$envValue
) {
// reset the environment variables
putenv(build_env_name(ClientResolver::ENV_FORMAT_REGION_SERVICE, $region, $service) . '=');
putenv(build_env_name(ClientResolver::ENV_FORMAT_SERVICE, $service) . '=');
// apply given environment
putenv($envName . '=' . $envValue);

$testValues = [
'endpoint_provider' => $this->createMock('\Aws\Endpoint\PartitionInterface'),
'service' => $service,
'region' => $region,
'scheme' => 'http'
];
$testValues['endpoint_provider']->method('isRegionMatch')->willReturn(true);
$testValues['endpoint_provider']->method('__invoke')->willReturn([
'endpoint' => 'this-would-be-the-actual-endpoint'
]);

$resolverArgs = array_intersect_key(
ClientResolver::getDefaultArguments(),
array_flip(array_keys($testValues))
);
$resolver = new ClientResolver($resolverArgs);

$resolved = $resolver->resolve($testValues, new HandlerList);
$this->assertSame($envValue, $resolved['endpoint']);
}

public function endpointValueConfiguredInEnvironmentVariableProvider()
{
return [
// Using region and service specific environment variable
['service' => 's3', 'region' => 'us-west-1', 'envName' => 'AWS_US_WEST_1_S3_ENDPOINT', 'envValue' => 'foo'],
// Using service specific environment variable only
['service' => 'my-service', 'region' => 'south-pole-1', 'envName' => 'AWS_MY_SERVICE_ENDPOINT', 'envValue' => 'bar']
];
}

/**
* @dataProvider partitionReturnProvider
Expand Down
11 changes: 11 additions & 0 deletions tests/FunctionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,15 @@ public function testSerializesHttpRequests()
$this->assertTrue($request->hasHeader('X-Amz-Date'));
$this->assertEquals('123', (string) $request->getBody());
}

/**
* @covers \Aws\build_env_name
* @covers \Aws\prepare_env_name
*/
public function testBuildEnvName()
{
$this->assertSame('FOO_BAR_BAZ', Aws\build_env_name('FOO_%s_%s', 'bar', 'bAz'));
$this->assertSame('FOO_BAR_BAZ', Aws\build_env_name('FOO_%s', 'Bar-bAZ'));
$this->assertSame('THIS_DOG_SWAM_TO_MY_FISH', Aws\build_env_name('%s_SWAM_TO_%s', 'this-dog', 'my-fish'));
}
}

0 comments on commit 70f9e7f

Please sign in to comment.