Skip to content

Commit 5be0afe

Browse files
authored
[6.x] DynamoDB in CI suite (#36749)
* Set up DynamoDB testing * env variable * Random AWS keys * AWS endpoint * try different port * Try localhost * Dynamically create table * Add provider * uppercase * KeySchema * Update table * Apply fixes from StyleCI (#36746) * throughput * exception message * Switch env statement * Remove directory
1 parent ab703aa commit 5be0afe

File tree

4 files changed

+85
-25
lines changed

4 files changed

+85
-25
lines changed

.github/workflows/tests.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,20 @@ jobs:
6363
max_attempts: 5
6464
command: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress
6565

66+
- name: Setup DynamoDB Local
67+
uses: rrainn/[email protected]
68+
with:
69+
port: 8888
70+
6671
- name: Execute tests
6772
run: vendor/bin/phpunit --verbose
6873
env:
6974
DB_PORT: ${{ job.services.mysql.ports[3306] }}
7075
DB_USERNAME: root
76+
DYNAMODB_CACHE_TABLE: laravel_dynamodb_test
77+
DYNAMODB_ENDPOINT: "http://localhost:8888"
78+
AWS_ACCESS_KEY_ID: random_key
79+
AWS_SECRET_ACCESS_KEY: random_secret
7180

7281
windows_tests:
7382
runs-on: windows-latest

src/Illuminate/Cache/CacheManager.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
namespace Illuminate\Cache;
44

5-
use Aws\DynamoDb\DynamoDbClient;
65
use Closure;
76
use Illuminate\Contracts\Cache\Factory as FactoryContract;
87
use Illuminate\Contracts\Cache\Store;
98
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
10-
use Illuminate\Support\Arr;
119
use InvalidArgumentException;
1210

1311
/**
@@ -226,21 +224,9 @@ protected function createDatabaseDriver(array $config)
226224
*/
227225
protected function createDynamodbDriver(array $config)
228226
{
229-
$dynamoConfig = [
230-
'region' => $config['region'],
231-
'version' => 'latest',
232-
'endpoint' => $config['endpoint'] ?? null,
233-
];
234-
235-
if ($config['key'] && $config['secret']) {
236-
$dynamoConfig['credentials'] = Arr::only(
237-
$config, ['key', 'secret', 'token']
238-
);
239-
}
240-
241227
return $this->repository(
242228
new DynamoDbStore(
243-
new DynamoDbClient($dynamoConfig),
229+
$this->app['cache.dynamodb.client'],
244230
$config['table'],
245231
$config['attributes']['key'] ?? 'key',
246232
$config['attributes']['value'] ?? 'value',

src/Illuminate/Cache/CacheServiceProvider.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Illuminate\Cache;
44

5+
use Aws\DynamoDb\DynamoDbClient;
56
use Illuminate\Contracts\Support\DeferrableProvider;
7+
use Illuminate\Support\Arr;
68
use Illuminate\Support\ServiceProvider;
79
use Symfony\Component\Cache\Adapter\Psr16Adapter;
810

@@ -30,6 +32,19 @@ public function register()
3032
$this->app->singleton('memcached.connector', function () {
3133
return new MemcachedConnector;
3234
});
35+
36+
$this->app->singleton('cache.dynamodb.client', function ($app) {
37+
$config = $app['config']->get('cache.stores.dynamodb');
38+
39+
return new DynamoDbClient([
40+
'region' => $config['region'],
41+
'version' => 'latest',
42+
'endpoint' => $config['endpoint'] ?? null,
43+
'credentials' => Arr::only(
44+
$config, ['key', 'secret', 'token']
45+
),
46+
]);
47+
});
3348
}
3449

3550
/**
@@ -40,7 +55,7 @@ public function register()
4055
public function provides()
4156
{
4257
return [
43-
'cache', 'cache.store', 'cache.psr6', 'memcached.connector',
58+
'cache', 'cache.store', 'cache.psr6', 'memcached.connector', 'cache.dynamodb.client',
4459
];
4560
}
4661
}

tests/Integration/Cache/DynamoDbStoreTest.php

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Illuminate\Tests\Integration\Cache;
44

5+
use Aws\DynamoDb\DynamoDbClient;
6+
use Aws\Exception\AwsException;
57
use Illuminate\Support\Facades\Cache;
68
use Illuminate\Support\Str;
79
use Orchestra\Testbench\TestCase;
@@ -13,11 +15,11 @@ class DynamoDbStoreTest extends TestCase
1315
{
1416
protected function setUp(): void
1517
{
16-
parent::setUp();
17-
1818
if (! env('DYNAMODB_CACHE_TABLE')) {
1919
$this->markTestSkipped('DynamoDB not configured.');
2020
}
21+
22+
parent::setUp();
2123
}
2224

2325
public function testItemsCanBeStoredAndRetrieved()
@@ -74,15 +76,63 @@ public function testLocksCanBeAcquired()
7476
*/
7577
protected function getEnvironmentSetUp($app)
7678
{
79+
if (! env('DYNAMODB_CACHE_TABLE')) {
80+
$this->markTestSkipped('DynamoDB not configured.');
81+
}
82+
7783
$app['config']->set('cache.default', 'dynamodb');
7884

79-
$app['config']->set('cache.stores.dynamodb', [
80-
'driver' => 'dynamodb',
81-
'key' => env('AWS_ACCESS_KEY_ID'),
82-
'secret' => env('AWS_SECRET_ACCESS_KEY'),
83-
'region' => 'us-east-1',
84-
'table' => env('DYNAMODB_CACHE_TABLE', 'laravel_test'),
85-
'endpoint' => env('DYNAMODB_ENDPOINT'),
85+
$config = $app['config']->get('cache.stores.dynamodb');
86+
87+
/** @var \Aws\DynamoDb\DynamoDbClient $client */
88+
$client = $app['cache.dynamodb.client'];
89+
90+
if ($this->dynamoTableExists($client, $config['table'])) {
91+
return;
92+
}
93+
94+
$client->createTable([
95+
'TableName' => $config['table'],
96+
'KeySchema' => [
97+
[
98+
'AttributeName' => $config['attributes']['key'] ?? 'key',
99+
'KeyType' => 'HASH',
100+
],
101+
],
102+
'AttributeDefinitions' => [
103+
[
104+
'AttributeName' => $config['attributes']['key'] ?? 'key',
105+
'AttributeType' => 'S',
106+
],
107+
],
108+
'ProvisionedThroughput' => [
109+
'ReadCapacityUnits' => 1,
110+
'WriteCapacityUnits' => 1,
111+
],
86112
]);
87113
}
114+
115+
/**
116+
* Determine if the given DynamoDB table exists.
117+
*
118+
* @param \Aws\DynamoDb\DynamoDbClient $client
119+
* @param string $table
120+
* @return bool
121+
*/
122+
public function dynamoTableExists(DynamoDbClient $client, $table)
123+
{
124+
try {
125+
$client->describeTable([
126+
'TableName' => $table,
127+
]);
128+
129+
return true;
130+
} catch (AwsException $e) {
131+
if (Str::contains($e->getAwsErrorMessage(), ['resource not found', 'Cannot do operations on a non-existent table'])) {
132+
return false;
133+
}
134+
135+
throw $e;
136+
}
137+
}
88138
}

0 commit comments

Comments
 (0)