Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.x] DynamoDB in CI suite #36749

Merged
merged 16 commits into from
Mar 25, 2021
9 changes: 9 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,20 @@ jobs:
max_attempts: 5
command: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress

- name: Setup DynamoDB Local
uses: rrainn/dynamodb-action@v2.0.0
with:
port: 8888

- name: Execute tests
run: vendor/bin/phpunit --verbose
env:
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DB_USERNAME: root
DYNAMODB_CACHE_TABLE: laravel_dynamodb_test
DYNAMODB_ENDPOINT: "http://localhost:8888"
AWS_ACCESS_KEY_ID: random_key
AWS_SECRET_ACCESS_KEY: random_secret

windows_tests:
runs-on: windows-latest
Expand Down
16 changes: 1 addition & 15 deletions src/Illuminate/Cache/CacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

namespace Illuminate\Cache;

use Aws\DynamoDb\DynamoDbClient;
use Closure;
use Illuminate\Contracts\Cache\Factory as FactoryContract;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Support\Arr;
use InvalidArgumentException;

/**
Expand Down Expand Up @@ -226,21 +224,9 @@ protected function createDatabaseDriver(array $config)
*/
protected function createDynamodbDriver(array $config)
{
$dynamoConfig = [
'region' => $config['region'],
'version' => 'latest',
'endpoint' => $config['endpoint'] ?? null,
];

if ($config['key'] && $config['secret']) {
$dynamoConfig['credentials'] = Arr::only(
$config, ['key', 'secret', 'token']
);
}

return $this->repository(
new DynamoDbStore(
new DynamoDbClient($dynamoConfig),
$this->app['cache.dynamodb.client'],
$config['table'],
$config['attributes']['key'] ?? 'key',
$config['attributes']['value'] ?? 'value',
Expand Down
17 changes: 16 additions & 1 deletion src/Illuminate/Cache/CacheServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Illuminate\Cache;

use Aws\DynamoDb\DynamoDbClient;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Cache\Adapter\Psr16Adapter;

Expand Down Expand Up @@ -30,6 +32,19 @@ public function register()
$this->app->singleton('memcached.connector', function () {
return new MemcachedConnector;
});

$this->app->singleton('cache.dynamodb.client', function ($app) {
$config = $app['config']->get('cache.stores.dynamodb');

return new DynamoDbClient([
'region' => $config['region'],
'version' => 'latest',
'endpoint' => $config['endpoint'] ?? null,
'credentials' => Arr::only(
$config, ['key', 'secret', 'token']
),
]);
});
}

/**
Expand All @@ -40,7 +55,7 @@ public function register()
public function provides()
{
return [
'cache', 'cache.store', 'cache.psr6', 'memcached.connector',
'cache', 'cache.store', 'cache.psr6', 'memcached.connector', 'cache.dynamodb.client',
];
}
}
68 changes: 59 additions & 9 deletions tests/Integration/Cache/DynamoDbStoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Illuminate\Tests\Integration\Cache;

use Aws\DynamoDb\DynamoDbClient;
use Aws\Exception\AwsException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Orchestra\Testbench\TestCase;
Expand All @@ -13,11 +15,11 @@ class DynamoDbStoreTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();

if (! env('DYNAMODB_CACHE_TABLE')) {
$this->markTestSkipped('DynamoDB not configured.');
}

parent::setUp();
}

public function testItemsCanBeStoredAndRetrieved()
Expand Down Expand Up @@ -74,15 +76,63 @@ public function testLocksCanBeAcquired()
*/
protected function getEnvironmentSetUp($app)
{
if (! env('DYNAMODB_CACHE_TABLE')) {
$this->markTestSkipped('DynamoDB not configured.');
}

$app['config']->set('cache.default', 'dynamodb');

$app['config']->set('cache.stores.dynamodb', [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => 'us-east-1',
'table' => env('DYNAMODB_CACHE_TABLE', 'laravel_test'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
$config = $app['config']->get('cache.stores.dynamodb');

/** @var \Aws\DynamoDb\DynamoDbClient $client */
$client = $app['cache.dynamodb.client'];

if ($this->dynamoTableExists($client, $config['table'])) {
return;
}

$client->createTable([
'TableName' => $config['table'],
'KeySchema' => [
[
'AttributeName' => $config['attributes']['key'] ?? 'key',
'KeyType' => 'HASH',
],
],
'AttributeDefinitions' => [
[
'AttributeName' => $config['attributes']['key'] ?? 'key',
'AttributeType' => 'S',
],
],
'ProvisionedThroughput' => [
'ReadCapacityUnits' => 1,
'WriteCapacityUnits' => 1,
],
]);
}

/**
* Determine if the given DynamoDB table exists.
*
* @param \Aws\DynamoDb\DynamoDbClient $client
* @param string $table
* @return bool
*/
public function dynamoTableExists(DynamoDbClient $client, $table)
{
try {
$client->describeTable([
'TableName' => $table,
]);

return true;
} catch (AwsException $e) {
if (Str::contains($e->getAwsErrorMessage(), ['resource not found', 'Cannot do operations on a non-existent table'])) {
return false;
}

throw $e;
}
}
}