From ab703aa6d5358c162df212d7924f17eaf26aaa73 Mon Sep 17 00:00:00 2001 From: Tetiana Blindaruk Date: Tue, 23 Mar 2021 19:44:14 +0200 Subject: [PATCH 1/5] [6.x] update changelog --- CHANGELOG-6.x.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-6.x.md b/CHANGELOG-6.x.md index 226fdd550d8a..cc073b4d93fb 100644 --- a/CHANGELOG-6.x.md +++ b/CHANGELOG-6.x.md @@ -1,6 +1,15 @@ # Release Notes for 6.x -## [Unreleased](https://github.com/laravel/framework/compare/v6.20.19...6.x) +## [Unreleased](https://github.com/laravel/framework/compare/v6.20.20...6.x) + + +## [v6.20.20 (2021-03-23)](https://github.com/laravel/framework/compare/v6.20.19...v6.20.20) + +### Added +- Added WSREP communication link failure for lost connection detection ([#36668](https://github.com/laravel/framework/pull/36668)) + +### Fixed +- Fixes the issue using cache:clear with PhpRedis and a clustered Redis instance. ([#36665](https://github.com/laravel/framework/pull/36665)) ## [v6.20.19 (2021-03-16)](https://github.com/laravel/framework/compare/v6.20.18...v6.20.19) From 5be0afe0f5a712a8256c0f6cfad6842c2bd779a1 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 25 Mar 2021 19:01:53 +0100 Subject: [PATCH 2/5] [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 --- .github/workflows/tests.yml | 9 +++ src/Illuminate/Cache/CacheManager.php | 16 +---- src/Illuminate/Cache/CacheServiceProvider.php | 17 ++++- tests/Integration/Cache/DynamoDbStoreTest.php | 68 ++++++++++++++++--- 4 files changed, 85 insertions(+), 25 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1a81af4975b9..ffe3c5a7b2e4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 diff --git a/src/Illuminate/Cache/CacheManager.php b/src/Illuminate/Cache/CacheManager.php index 33d1027bce1a..42bfc7271d59 100755 --- a/src/Illuminate/Cache/CacheManager.php +++ b/src/Illuminate/Cache/CacheManager.php @@ -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; /** @@ -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', diff --git a/src/Illuminate/Cache/CacheServiceProvider.php b/src/Illuminate/Cache/CacheServiceProvider.php index 46fa0ae2615c..90d1d019f4be 100755 --- a/src/Illuminate/Cache/CacheServiceProvider.php +++ b/src/Illuminate/Cache/CacheServiceProvider.php @@ -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; @@ -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'] + ), + ]); + }); } /** @@ -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', ]; } } diff --git a/tests/Integration/Cache/DynamoDbStoreTest.php b/tests/Integration/Cache/DynamoDbStoreTest.php index 74897fbde8cb..f7aeae6a3deb 100644 --- a/tests/Integration/Cache/DynamoDbStoreTest.php +++ b/tests/Integration/Cache/DynamoDbStoreTest.php @@ -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; @@ -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() @@ -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; + } + } } From efba08c637bd39ecbb1a5279b3f43965e1807f5e Mon Sep 17 00:00:00 2001 From: Jitendra Date: Fri, 26 Mar 2021 20:18:48 +0530 Subject: [PATCH 3/5] Removed filter on username for redis configuration parameter. (#36762) Co-authored-by: dschobert --- src/Illuminate/Redis/RedisManager.php | 2 +- tests/Redis/RedisConnectorTest.php | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Redis/RedisManager.php b/src/Illuminate/Redis/RedisManager.php index b5d98203c180..8a6c88d1c2ba 100644 --- a/src/Illuminate/Redis/RedisManager.php +++ b/src/Illuminate/Redis/RedisManager.php @@ -192,7 +192,7 @@ protected function parseConnectionConfiguration($config) } return array_filter($parsed, function ($key) { - return ! in_array($key, ['driver', 'username'], true); + return ! in_array($key, ['driver'], true); }, ARRAY_FILTER_USE_KEY); } diff --git a/tests/Redis/RedisConnectorTest.php b/tests/Redis/RedisConnectorTest.php index 599fa2f2aad3..0203ed9d9b82 100644 --- a/tests/Redis/RedisConnectorTest.php +++ b/tests/Redis/RedisConnectorTest.php @@ -160,4 +160,27 @@ public function testScheme() $this->assertEquals("tcp://{$host}", $phpRedisClient->getHost()); $this->assertEquals($port, $phpRedisClient->getPort()); } + + public function testPredisConfigurationWithUsername() + { + $host = env('REDIS_HOST', '127.0.0.1'); + $port = env('REDIS_PORT', 6379); + $username = 'testuser'; + $password = 'testpw'; + + $predis = new RedisManager(new Application, 'predis', [ + 'default' => [ + 'host' => $host, + 'port' => $port, + 'username' => $username, + 'password' => $password, + 'database' => 5, + 'timeout' => 0.5, + ], + ]); + $predisClient = $predis->connection()->client(); + $parameters = $predisClient->getConnection()->getParameters(); + $this->assertEquals($username, $parameters->username); + $this->assertEquals($password, $parameters->password); + } } From 006ba38124df6a8a651546a0301d604665b394b7 Mon Sep 17 00:00:00 2001 From: vdlp-mw <47185594+vdlp-mw@users.noreply.github.com> Date: Fri, 26 Mar 2021 16:54:12 +0100 Subject: [PATCH 4/5] Use qualified column names in pivot query (#36720) Co-authored-by: Menzo Wijmenga --- .../Eloquent/Relations/Concerns/InteractsWithPivotTable.php | 4 ++-- tests/Database/DatabaseEloquentMorphToManyTest.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php b/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php index c6812b75a150..b0abf2848590 100644 --- a/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php +++ b/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php @@ -429,7 +429,7 @@ public function detach($ids = null, $touch = true) return 0; } - $query->whereIn($this->relatedPivotKey, (array) $ids); + $query->whereIn($this->getQualifiedRelatedPivotKeyName(), (array) $ids); } // Once we have all of the conditions set on the statement, we are ready @@ -544,7 +544,7 @@ public function newPivotQuery() $query->whereIn(...$arguments); } - return $query->where($this->foreignPivotKey, $this->parent->{$this->parentKey}); + return $query->where($this->getQualifiedForeignPivotKeyName(), $this->parent->{$this->parentKey}); } /** diff --git a/tests/Database/DatabaseEloquentMorphToManyTest.php b/tests/Database/DatabaseEloquentMorphToManyTest.php index 0b4a7f511074..dac94e258c39 100644 --- a/tests/Database/DatabaseEloquentMorphToManyTest.php +++ b/tests/Database/DatabaseEloquentMorphToManyTest.php @@ -47,9 +47,9 @@ public function testDetachRemovesPivotTableRecord() $relation = $this->getMockBuilder(MorphToMany::class)->setMethods(['touchIfTouching'])->setConstructorArgs($this->getRelationArguments())->getMock(); $query = m::mock(stdClass::class); $query->shouldReceive('from')->once()->with('taggables')->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_id', 1)->andReturn($query); + $query->shouldReceive('where')->once()->with('taggables.taggable_id', 1)->andReturn($query); $query->shouldReceive('where')->once()->with('taggable_type', get_class($relation->getParent()))->andReturn($query); - $query->shouldReceive('whereIn')->once()->with('tag_id', [1, 2, 3]); + $query->shouldReceive('whereIn')->once()->with('taggables.tag_id', [1, 2, 3]); $query->shouldReceive('delete')->once()->andReturn(true); $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock(stdClass::class)); $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); @@ -63,7 +63,7 @@ public function testDetachMethodClearsAllPivotRecordsWhenNoIDsAreGiven() $relation = $this->getMockBuilder(MorphToMany::class)->setMethods(['touchIfTouching'])->setConstructorArgs($this->getRelationArguments())->getMock(); $query = m::mock(stdClass::class); $query->shouldReceive('from')->once()->with('taggables')->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_id', 1)->andReturn($query); + $query->shouldReceive('where')->once()->with('taggables.taggable_id', 1)->andReturn($query); $query->shouldReceive('where')->once()->with('taggable_type', get_class($relation->getParent()))->andReturn($query); $query->shouldReceive('whereIn')->never(); $query->shouldReceive('delete')->once()->andReturn(true); From 35e339bffda785ae0cee11c66a17644a9fa096d1 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 30 Mar 2021 09:08:57 -0500 Subject: [PATCH 5/5] patch --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 4e4d6c1840d3..a4f66d94d1f6 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -31,7 +31,7 @@ class Application extends Container implements ApplicationContract, HttpKernelIn * * @var string */ - const VERSION = '6.20.20'; + const VERSION = '6.20.21'; /** * The base path for the Laravel installation.