From 3806fe03817dcb3882b2e3d449126cec37595ee8 Mon Sep 17 00:00:00 2001 From: Nadiya Syvokonenko Date: Wed, 28 Oct 2020 23:41:43 -0500 Subject: [PATCH] MCLOUD-7098: Validation which compare service versions and magento version doesn't work on PRO (#6) --- src/Config/Validator/Deploy/ServiceEol.php | 8 +- .../Validator/Deploy/ServiceVersion.php | 15 +- src/DB/Data/ConnectionTypes.php | 93 ++++++++ src/DB/Data/RelationshipConnectionFactory.php | 24 +- src/Service/Database.php | 101 +++------ src/Service/Php.php | 16 +- src/Service/RabbitMq.php | 30 ++- src/Service/Redis.php | 37 ++- .../Validator/Deploy/ServiceVersionTest.php | 23 +- src/Test/Unit/DB/Data/ConnectionTypesTest.php | 169 ++++++++++++++ .../RelationshipConnectionFactoryTest.php | 12 +- src/Test/Unit/Service/DatabaseTest.php | 210 +++++++----------- src/Test/Unit/Service/RabbitMqTest.php | 100 ++++++++- src/Test/Unit/Service/RedisTest.php | 128 +++++++++-- 14 files changed, 698 insertions(+), 268 deletions(-) create mode 100644 src/DB/Data/ConnectionTypes.php create mode 100644 src/Test/Unit/DB/Data/ConnectionTypesTest.php diff --git a/src/Config/Validator/Deploy/ServiceEol.php b/src/Config/Validator/Deploy/ServiceEol.php index f1c270b739..96364ba500 100644 --- a/src/Config/Validator/Deploy/ServiceEol.php +++ b/src/Config/Validator/Deploy/ServiceEol.php @@ -8,11 +8,10 @@ namespace Magento\MagentoCloud\Config\Validator\Deploy; use Magento\MagentoCloud\App\Error; +use Magento\MagentoCloud\App\GenericException; use Magento\MagentoCloud\Config\Validator; -use Magento\MagentoCloud\Filesystem\FileSystemException; use Magento\MagentoCloud\Service\EolValidator as EOLValidator; use Magento\MagentoCloud\Config\ValidatorInterface; -use Magento\MagentoCloud\Service\ServiceMismatchException; /** * Class to check if services approaching their EOLs. @@ -52,8 +51,7 @@ public function __construct( /** * Get the defined services and versions and check for their EOLs by error level. * - * @return Validator\ResultInterface - * @throws FileSystemException + * {@inheritDoc} */ public function validate(): Validator\ResultInterface { @@ -70,7 +68,7 @@ public function validate(): Validator\ResultInterface $this->errorLevel == ValidatorInterface::LEVEL_WARNING ? Error::WARN_SERVICE_PASSED_EOL : null ); } - } catch (ServiceMismatchException $e) { + } catch (GenericException $e) { return $this->resultFactory->error('Can\'t validate version of some services: ' . $e->getMessage()); } diff --git a/src/Config/Validator/Deploy/ServiceVersion.php b/src/Config/Validator/Deploy/ServiceVersion.php index 4170186b7b..43ab96cb21 100644 --- a/src/Config/Validator/Deploy/ServiceVersion.php +++ b/src/Config/Validator/Deploy/ServiceVersion.php @@ -14,6 +14,7 @@ use Magento\MagentoCloud\Service\Validator as ServiceVersionValidator; use Magento\MagentoCloud\Config\Validator; use Magento\MagentoCloud\Config\ValidatorInterface; +use Psr\Log\LoggerInterface; /** * Validates installed service versions according to version mapping. @@ -36,19 +37,27 @@ class ServiceVersion implements ValidatorInterface */ private $serviceFactory; + /** + * @var LoggerInterface + */ + private $logger; + /** * @param Validator\ResultFactory $resultFactory * @param ServiceVersionValidator $serviceVersionValidator * @param ServiceFactory $serviceFactory + * @param LoggerInterface $logger */ public function __construct( Validator\ResultFactory $resultFactory, ServiceVersionValidator $serviceVersionValidator, - ServiceFactory $serviceFactory + ServiceFactory $serviceFactory, + LoggerInterface $logger ) { $this->resultFactory = $resultFactory; $this->serviceVersionValidator = $serviceVersionValidator; $this->serviceFactory = $serviceFactory; + $this->logger = $logger; } /** @@ -69,6 +78,10 @@ public function validate(): Validator\ResultInterface foreach ($services as $serviceName) { $service = $this->serviceFactory->create($serviceName); $serviceVersion = $service->getVersion(); + + $logMsq = $serviceVersion ? 'is ' . $serviceVersion : 'is not detected'; + $this->logger->info(sprintf('Version of service \'%s\' %s', $serviceName, $logMsq)); + if ($serviceVersion !== '0' && $error = $this->serviceVersionValidator->validateService($serviceName, $serviceVersion) ) { diff --git a/src/DB/Data/ConnectionTypes.php b/src/DB/Data/ConnectionTypes.php new file mode 100644 index 0000000000..02605986d6 --- /dev/null +++ b/src/DB/Data/ConnectionTypes.php @@ -0,0 +1,93 @@ +environment = $environment; + } + + /** + * @inheritdoc + */ + public function getConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_KEY)[0] ?? []; + } + + /** + * Returns service configuration for slave. + * + * @return array + */ + public function getSlaveConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_SLAVE_KEY)[0] ?? []; + } + + /** + * Returns configuration for quote service. + */ + public function getQuoteConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_QUOTE_KEY)[0] ?? []; + } + + /** + * Returns configuration for quote slave service. + * + * @return array + */ + public function getQuoteSlaveConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_QUOTE_SLAVE_KEY)[0] ?? []; + } + + /** + * Returns configuration for sales service. + */ + public function getSalesConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_SALES_KEY)[0] ?? []; + } + + /** + * Returns configuration for slave sales service. + * + * @return array + */ + public function getSalesSlaveConfiguration(): array + { + return $this->environment->getRelationship(self::RELATIONSHIP_SALES_SLAVE_KEY)[0] ?? []; + } +} diff --git a/src/DB/Data/RelationshipConnectionFactory.php b/src/DB/Data/RelationshipConnectionFactory.php index 4f1db41519..ced3a8f5b5 100644 --- a/src/DB/Data/RelationshipConnectionFactory.php +++ b/src/DB/Data/RelationshipConnectionFactory.php @@ -7,8 +7,6 @@ namespace Magento\MagentoCloud\DB\Data; -use Magento\MagentoCloud\Service\Database; - /** * Responsible for creating and configuring Magento\MagentoCloud\DB\Data\ConnectionInterface instances. */ @@ -24,16 +22,16 @@ class RelationshipConnectionFactory const CONNECTION_SALES_SLAVE = 'sales-slave'; /** - * @var Database + * @var ConnectionTypes */ - private $database; + private $connectionType; /** - * @param Database $database + * @param ConnectionTypes $connectionType */ - public function __construct(Database $database) + public function __construct(ConnectionTypes $connectionType) { - $this->database = $database; + $this->connectionType = $connectionType; } /** @@ -47,22 +45,22 @@ public function create(string $connectionType): ConnectionInterface { switch ($connectionType) { case self::CONNECTION_MAIN: - $configuration = $this->database->getConfiguration(); + $configuration = $this->connectionType->getConfiguration(); break; case self::CONNECTION_SLAVE: - $configuration = $this->database->getSlaveConfiguration(); + $configuration = $this->connectionType->getSlaveConfiguration(); break; case self::CONNECTION_QUOTE_MAIN: - $configuration = $this->database->getQuoteConfiguration(); + $configuration = $this->connectionType->getQuoteConfiguration(); break; case self::CONNECTION_QUOTE_SLAVE: - $configuration = $this->database->getQuoteSlaveConfiguration(); + $configuration = $this->connectionType->getQuoteSlaveConfiguration(); break; case self::CONNECTION_SALES_MAIN: - $configuration = $this->database->getSalesConfiguration(); + $configuration = $this->connectionType->getSalesConfiguration(); break; case self::CONNECTION_SALES_SLAVE: - $configuration = $this->database->getSalesSlaveConfiguration(); + $configuration = $this->connectionType->getSalesSlaveConfiguration(); break; default: throw new \RuntimeException( diff --git a/src/Service/Database.php b/src/Service/Database.php index 6a0e3be181..3c6f37b00b 100644 --- a/src/Service/Database.php +++ b/src/Service/Database.php @@ -7,26 +7,23 @@ namespace Magento\MagentoCloud\Service; -use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\DB\ConnectionInterface; +use Magento\MagentoCloud\DB\Data\ConnectionTypes; /** - * Returns database service configurations. + * Returns main database service configurations. */ class Database implements ServiceInterface { - const RELATIONSHIP_KEY = 'database'; - const RELATIONSHIP_SLAVE_KEY = 'database-slave'; - - const RELATIONSHIP_QUOTE_KEY = 'database-quote'; - const RELATIONSHIP_QUOTE_SLAVE_KEY = 'database-quote-slave'; - - const RELATIONSHIP_SALES_KEY = 'database-sales'; - const RELATIONSHIP_SALES_SLAVE_KEY = 'database-sales-slave'; + /** + * @var ConnectionTypes + */ + private $connectionType; /** - * @var Environment + * @var ConnectionInterface */ - private $environment; + private $connection; /** * @var string @@ -34,11 +31,15 @@ class Database implements ServiceInterface private $version; /** - * @param Environment $environment + * @param ConnectionTypes $connectionType + * @param ConnectionInterface $connection */ - public function __construct(Environment $environment) - { - $this->environment = $environment; + public function __construct( + ConnectionTypes $connectionType, + ConnectionInterface $connection + ) { + $this->connectionType = $connectionType; + $this->connection = $connection; } /** @@ -46,69 +47,33 @@ public function __construct(Environment $environment) */ public function getConfiguration(): array { - return $this->environment->getRelationship(self::RELATIONSHIP_KEY)[0] ?? []; - } - - /** - * Returns service configuration for slave. - * - * @return array - */ - public function getSlaveConfiguration(): array - { - return $this->environment->getRelationship(self::RELATIONSHIP_SLAVE_KEY)[0] ?? []; - } - - /** - * Returns configuration for quote service. - */ - public function getQuoteConfiguration(): array - { - return $this->environment->getRelationship(self::RELATIONSHIP_QUOTE_KEY)[0] ?? []; - } - - /** - * Returns configuration for quote slave service. - * - * @return array - */ - public function getQuoteSlaveConfiguration(): array - { - return $this->environment->getRelationship(self::RELATIONSHIP_QUOTE_SLAVE_KEY)[0] ?? []; + return $this->connectionType->getConfiguration(); } /** - * Returns configuration for sales service. - */ - public function getSalesConfiguration(): array - { - return $this->environment->getRelationship(self::RELATIONSHIP_SALES_KEY)[0] ?? []; - } - - /** - * Returns configuration for slave sales service. - * - * @return array - */ - public function getSalesSlaveConfiguration(): array - { - return $this->environment->getRelationship(self::RELATIONSHIP_SALES_SLAVE_KEY)[0] ?? []; - } - - /** - * Returns version of the service. + * Retrieves MySQL service version whether from relationship configuration + * or using SQL query (for PRO environments) * - * @return string + * {@inheritDoc} */ public function getVersion(): string { if ($this->version === null) { $this->version = '0'; - $databaseConfig = $this->getConfiguration(); + try { + $databaseConfig = $this->getConfiguration(); + + if (isset($databaseConfig['type']) && strpos($databaseConfig['type'], ':') !== false) { + $this->version = explode(':', $databaseConfig['type'])[1]; + } elseif (!empty($databaseConfig['host'])) { + $rawVersion = $this->connection->selectOne('SELECT VERSION() as version'); + preg_match('/^\d+\.\d+/', $rawVersion['version'] ?? '', $matches); - if (isset($databaseConfig['type']) && strpos($databaseConfig['type'], ':') !== false) { - $this->version = explode(':', $databaseConfig['type'])[1]; + $this->version = $matches[0] ?? '0'; + } + } catch (\Exception $e) { + throw new ServiceException($e->getMessage()); } } diff --git a/src/Service/Php.php b/src/Service/Php.php index e841a6c731..c3048efd70 100644 --- a/src/Service/Php.php +++ b/src/Service/Php.php @@ -12,11 +12,6 @@ */ class Php implements ServiceInterface { - /** - * @var string - */ - private $version; - /** * Get PHP configuration. * @@ -34,15 +29,6 @@ public function getConfiguration(): array */ public function getVersion(): string { - if ($this->version === null) { - $this->version = '0'; - - $phpConfigs = $this->getConfiguration(); - if (isset($phpConfigs['version'])) { - $this->version = $phpConfigs['version']; - } - } - - return $this->version; + return $this->getConfiguration()['version']; } } diff --git a/src/Service/RabbitMq.php b/src/Service/RabbitMq.php index a9217321df..a7fad83d3c 100644 --- a/src/Service/RabbitMq.php +++ b/src/Service/RabbitMq.php @@ -8,6 +8,8 @@ namespace Magento\MagentoCloud\Service; use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\Shell\ShellException; +use Magento\MagentoCloud\Shell\ShellInterface; /** * @@ -26,6 +28,11 @@ class RabbitMq implements ServiceInterface */ private $environment; + /** + * @var ShellInterface + */ + private $shell; + /** * @var string */ @@ -33,17 +40,21 @@ class RabbitMq implements ServiceInterface /** * @param Environment $environment + * @param ShellInterface $shell */ - public function __construct(Environment $environment) - { + public function __construct( + Environment $environment, + ShellInterface $shell + ) { $this->environment = $environment; + $this->shell = $shell; } /** * Finds if configuration exists for one of possible amqp relationship names and return first match, * amqp relationship can have different name on different environment. * - * {@inheritdoc} + * {@inheritDoc} */ public function getConfiguration(): array { @@ -58,7 +69,10 @@ public function getConfiguration(): array } /** - * @inheritdoc + * Retrieve RabbitMQ service version whether from relationship configuration + * or using CLI command (for PRO environments) + * + * {@inheritDoc} */ public function getVersion(): string { @@ -69,6 +83,14 @@ public function getVersion(): string if (isset($config['type']) && strpos($config['type'], ':') !== false) { $this->version = explode(':', $config['type'])[1]; + } elseif (isset($config['host']) && isset($config['port'])) { + try { + $process = $this->shell->execute('dpkg -s rabbitmq-server | grep Version'); + preg_match('/^(?:Version:(?:\s)?)(\d+\.\d+)/', $process->getOutput(), $matches); + $this->version = $matches[1] ?? '0'; + } catch (ShellException $exception) { + throw new ServiceException($exception->getMessage()); + } } } diff --git a/src/Service/Redis.php b/src/Service/Redis.php index b468f3c1d9..7a8d50d885 100644 --- a/src/Service/Redis.php +++ b/src/Service/Redis.php @@ -8,6 +8,8 @@ namespace Magento\MagentoCloud\Service; use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\Shell\ShellException; +use Magento\MagentoCloud\Shell\ShellInterface; /** * Returns Redis service configurations. @@ -22,6 +24,11 @@ class Redis implements ServiceInterface */ private $environment; + /** + * @var ShellInterface + */ + private $shell; + /** * @var string */ @@ -29,10 +36,14 @@ class Redis implements ServiceInterface /** * @param Environment $environment + * @param ShellInterface $shell */ - public function __construct(Environment $environment) - { + public function __construct( + Environment $environment, + ShellInterface $shell + ) { $this->environment = $environment; + $this->shell = $shell; } /** @@ -54,19 +65,35 @@ public function getSlaveConfiguration(): array } /** - * Returns version of the service. + * Retrieves Redis service version whether from relationship configuration + * or using CLI command (for PRO environments) * - * @return string + * {@inheritDoc} */ public function getVersion(): string { if ($this->version === null) { $this->version = '0'; - $redisConfig = $this->getConfiguration(); + //on integration environments if (isset($redisConfig['type']) && strpos($redisConfig['type'], ':') !== false) { $this->version = explode(':', $redisConfig['type'])[1]; + } elseif (isset($redisConfig['host']) && isset($redisConfig['port'])) { + //on dedicated environments + try { + $process = $this->shell->execute( + sprintf( + 'redis-cli -p %s -h %s info | grep redis_version', + $redisConfig['port'], + $redisConfig['host'] + ) + ); + preg_match('/^(?:redis_version:)(\d+\.\d+)/', $process->getOutput(), $matches); + $this->version = $matches[1] ?? '0'; + } catch (ShellException $exception) { + throw new ServiceException($exception->getMessage()); + } } } diff --git a/src/Test/Unit/Config/Validator/Deploy/ServiceVersionTest.php b/src/Test/Unit/Config/Validator/Deploy/ServiceVersionTest.php index 8ee187bc5c..3d0a2db765 100644 --- a/src/Test/Unit/Config/Validator/Deploy/ServiceVersionTest.php +++ b/src/Test/Unit/Config/Validator/Deploy/ServiceVersionTest.php @@ -17,6 +17,7 @@ use Magento\MagentoCloud\Config\Validator\ResultFactory; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; /** * @inheritdoc @@ -38,6 +39,11 @@ class ServiceVersionTest extends TestCase */ private $serviceVersionValidatorMock; + /** + * @var LoggerInterface|MockObject + */ + private $loggerMock; + /** * @var ServiceFactory|MockObject */ @@ -54,15 +60,17 @@ protected function setUp() ]); $this->serviceVersionValidatorMock = $this->createMock(ServiceVersionValidator::class); $this->serviceFactory = $this->createMock(ServiceFactory::class); + $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); $this->validator = new ServiceVersion( $this->resultFactoryMock, $this->serviceVersionValidatorMock, - $this->serviceFactory + $this->serviceFactory, + $this->loggerMock ); } - public function testValidate() + public function testValidate(): void { $service1 = $this->createMock(ServiceInterface::class); $service1->expects($this->once()) @@ -79,6 +87,13 @@ public function testValidate() $this->serviceFactory->expects($this->exactly(3)) ->method('create') ->willReturnOnConsecutiveCalls($service1, $service2, $service3); + $this->loggerMock->expects($this->exactly(3)) + ->method('info') + ->withConsecutive( + ['Version of service \'rabbitmq\' is not detected', []], + ['Version of service \'redis\' is 3.2', []], + ['Version of service \'mysql\' is 10.2', []] + ); $this->serviceVersionValidatorMock->expects($this->exactly(2)) ->method('validateService') ->withConsecutive( @@ -92,7 +107,7 @@ public function testValidate() $this->validator->validate(); } - public function testValidateWithErrors() + public function testValidateWithErrors(): void { $errorMessages = ['error message 1', 'error message 2', 'error message 3']; $service1 = $this->createMock(ServiceInterface::class); @@ -125,7 +140,7 @@ public function testValidateWithErrors() $this->validator->validate(); } - public function testValidateWithException() + public function testValidateWithException(): void { $this->serviceFactory->expects($this->any()) ->method('create') diff --git a/src/Test/Unit/DB/Data/ConnectionTypesTest.php b/src/Test/Unit/DB/Data/ConnectionTypesTest.php new file mode 100644 index 0000000000..562f637dd3 --- /dev/null +++ b/src/Test/Unit/DB/Data/ConnectionTypesTest.php @@ -0,0 +1,169 @@ +environmentMock = $this->createMock(Environment::class); + + $this->connectionType = new ConnectionTypes( + $this->environmentMock + ); + } + + public function testGetConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3306', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3306', + ], + $this->connectionType->getConfiguration() + ); + } + + public function testGetSlaveConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_SLAVE_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3304', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3304', + ], + $this->connectionType->getSlaveConfiguration() + ); + } + + public function testGetQuoteConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_QUOTE_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3307', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3307', + ], + $this->connectionType->getQuoteConfiguration() + ); + } + + public function testGetQuoteSlaveConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_QUOTE_SLAVE_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3308', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3308', + ], + $this->connectionType->getQuoteSlaveConfiguration() + ); + } + + public function testGetSalesConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_SALES_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3309', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3309', + ], + $this->connectionType->getSalesConfiguration() + ); + } + + public function testGetSaleSlaveConfiguration(): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(ConnectionTypes::RELATIONSHIP_SALES_SLAVE_KEY) + ->willReturn([ + [ + 'host' => '127.0.0.1', + 'port' => '3310', + ] + ]); + + $this->assertSame( + [ + 'host' => '127.0.0.1', + 'port' => '3310', + ], + $this->connectionType->getSalesSlaveConfiguration() + ); + } +} diff --git a/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php b/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php index cbf96ac53d..046723ec6b 100644 --- a/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php +++ b/src/Test/Unit/DB/Data/RelationshipConnectionFactoryTest.php @@ -7,9 +7,9 @@ namespace Magento\MagentoCloud\Test\Unit\DB\Data; +use Magento\MagentoCloud\DB\Data\ConnectionTypes; use Magento\MagentoCloud\DB\Data\RelationshipConnection; use Magento\MagentoCloud\DB\Data\RelationshipConnectionFactory; -use Magento\MagentoCloud\Service\Database; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -24,19 +24,19 @@ class RelationshipConnectionFactoryTest extends TestCase private $factory; /** - * @var Database|MockObject + * @var ConnectionTypes|MockObject */ - private $databaseMock; + private $connectionTypeMock; /** * @inheritdoc */ protected function setUp() { - $this->databaseMock = $this->createMock(Database::class); + $this->connectionTypeMock = $this->createMock(ConnectionTypes::class); $this->factory = new RelationshipConnectionFactory( - $this->databaseMock + $this->connectionTypeMock ); } @@ -47,7 +47,7 @@ protected function setUp() */ public function testCreate(string $method, string $connectionType) { - $this->databaseMock->expects($this->once()) + $this->connectionTypeMock->expects($this->once()) ->method($method) ->willReturn([]); diff --git a/src/Test/Unit/Service/DatabaseTest.php b/src/Test/Unit/Service/DatabaseTest.php index 1c44a13b2a..8d5b4a9116 100644 --- a/src/Test/Unit/Service/DatabaseTest.php +++ b/src/Test/Unit/Service/DatabaseTest.php @@ -7,7 +7,8 @@ namespace Magento\MagentoCloud\Test\Unit\Service; -use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\DB\ConnectionInterface; +use Magento\MagentoCloud\DB\Data\ConnectionTypes; use Magento\MagentoCloud\Service\Database; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -19,176 +20,129 @@ class DatabaseTest extends TestCase { /** - * @var Database|MockObject + * @var Database */ private $database; /** - * @var Environment|MockObject + * @var ConnectionTypes|MockObject */ - private $environmentMock; + private $connectionTypeMock; + + /** + * @var ConnectionInterface|MockObject + */ + private $connectionMock; /** * @inheritdoc */ public function setUp() { - $this->environmentMock = $this->createMock(Environment::class); + $this->connectionTypeMock = $this->createMock(ConnectionTypes::class); + $this->connectionMock = $this->getMockForAbstractClass(ConnectionInterface::class); $this->database = new Database( - $this->environmentMock + $this->connectionTypeMock, + $this->connectionMock ); } - public function testGetConfiguration() + public function testGetConfiguration(): void { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_KEY) - ->willReturn([ - [ - 'host' => '127.0.0.1', - 'port' => '3306', - ] - ]); + $connection = [ + 'host' => '127.0.0.1', + 'port' => '3306', + ]; - $this->assertSame( - [ - 'host' => '127.0.0.1', - 'port' => '3306', - ], - $this->database->getConfiguration() - ); - } - - public function testGetSlaveConfiguration() - { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_SLAVE_KEY) - ->willReturn([ - [ - 'host' => '127.0.0.1', - 'port' => '3307', - ] - ]); + $this->connectionTypeMock->expects($this->once()) + ->method('getConfiguration') + ->willReturn($connection); $this->assertSame( - [ - 'host' => '127.0.0.1', - 'port' => '3307', - ], - $this->database->getSlaveConfiguration() + $connection, + $this->database->getConfiguration() ); } - public function testGetQuoteConfiguration() + /** + * @param array $config + * @param string $expectedVersion + * + * @dataProvider getVersionFromConfigDataProvider + */ + public function testGetVersionFromConfig(array $config, string $expectedVersion): void { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_QUOTE_KEY) - ->willReturn([ - [ - 'host' => '127.0.0.1', - 'port' => '3308', - ] - ]); + $this->connectionTypeMock->expects($this->once()) + ->method('getConfiguration') + ->willReturn($config); + $this->connectionMock->expects($this->never()) + ->method('selectOne'); - $this->assertSame( - [ - 'host' => '127.0.0.1', - 'port' => '3308', - ], - $this->database->getQuoteConfiguration() - ); + $this->assertEquals($expectedVersion, $this->database->getVersion()); } - public function testGetQuoteSlaveConfiguration() + /** + * Data provider for testGetVersionFromConfig + * @return array + */ + public function getVersionFromConfigDataProvider(): array { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_QUOTE_SLAVE_KEY) - ->willReturn([ - [ - 'host' => '127.0.0.1', - 'port' => '3309', - ] - ]); - - $this->assertSame( + return [ [ - 'host' => '127.0.0.1', - 'port' => '3309', - ], - $this->database->getQuoteSlaveConfiguration() - ); - } - - public function testGetSalesConfiguration() - { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_SALES_KEY) - ->willReturn([ [ 'host' => '127.0.0.1', - 'port' => '3308', - ] - ]); - - $this->assertSame( - [ - 'host' => '127.0.0.1', - 'port' => '3308', + 'port' => '3306', + 'type' => 'mysql:10.2', + ], + '10.2' ], - $this->database->getSalesConfiguration() - ); - } - - public function testGetSaleSlaveConfiguration() - { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_SALES_SLAVE_KEY) - ->willReturn([ - [ - 'host' => '127.0.0.1', - 'port' => '3309', - ] - ]); - - $this->assertSame( [ - 'host' => '127.0.0.1', - 'port' => '3309', - ], - $this->database->getSalesSlaveConfiguration() - ); + ['host' => ''], + '0' + ] + ]; } - public function testGetVersion() + /** + * @param array $version + * @param string $expectedResult + * @throws \Magento\MagentoCloud\Service\ServiceException + * + * @dataProvider getVersionDataProvider + */ + public function testGetVersion(array $version, string $expectedResult): void { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_KEY) - ->willReturn([ + $this->connectionTypeMock->expects($this->once()) + ->method('getConfiguration') + ->willReturn( [ 'host' => '127.0.0.1', 'port' => '3306', - 'type' => 'mysql:10.2', ] - ]); + ); - $this->assertEquals('10.2', $this->database->getVersion()); + $this->connectionMock->expects($this->once()) + ->method('selectOne') + ->with('SELECT VERSION() as version') + ->willReturn($version); + + $this->assertEquals($expectedResult, $this->database->getVersion()); } - public function testGetVersionNotConfigured() + /** + * Data provider for testGetVersion + * @return array + */ + public function getVersionDataProvider(): array { - $this->environmentMock->expects($this->once()) - ->method('getRelationship') - ->with(Database::RELATIONSHIP_KEY) - ->willReturn([]); - - $this->assertEquals('0', $this->database->getVersion()); + return [ + [['version' => '10.2.33-MariaDB-10.2.33+maria~stretch-lo'], '10.2'], + [['version' => '10.3.20-MariaDB-1:10.3.20+maria~jessie'], '10.3'], + [['version' => 's10.3.20-MariaDB-1:10.3.20+maria~jessie'], '0'], + [['version' => ''], '0'], + [['version' => '10.version'], '0'], + [[], '0'], + ]; } } diff --git a/src/Test/Unit/Service/RabbitMqTest.php b/src/Test/Unit/Service/RabbitMqTest.php index a2eeb32e34..1cf9cfe097 100644 --- a/src/Test/Unit/Service/RabbitMqTest.php +++ b/src/Test/Unit/Service/RabbitMqTest.php @@ -9,6 +9,10 @@ use Magento\MagentoCloud\Config\Environment; use Magento\MagentoCloud\Service\RabbitMq; +use Magento\MagentoCloud\Service\ServiceException; +use Magento\MagentoCloud\Shell\ProcessInterface; +use Magento\MagentoCloud\Shell\ShellException; +use Magento\MagentoCloud\Shell\ShellInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -28,19 +32,26 @@ class RabbitMqTest extends TestCase */ private $environmentMock; + /** + * @var ShellInterface|MockObject + */ + private $shellMock; + /** * @inheritdoc */ public function setUp() { $this->environmentMock = $this->createMock(Environment::class); + $this->shellMock = $this->getMockForAbstractClass(ShellInterface::class); $this->rabbitMq = new RabbitMq( - $this->environmentMock + $this->environmentMock, + $this->shellMock ); } - public function testGetConfiguration() + public function testGetConfiguration(): void { $this->environmentMock->expects($this->exactly(3)) ->method('getRelationship') @@ -65,7 +76,7 @@ public function testGetConfiguration() ); } - public function testGetVersion() + public function testGetVersion(): void { $this->environmentMock->expects($this->exactly(3)) ->method('getRelationship') @@ -82,15 +93,94 @@ public function testGetVersion() ] ); + $this->shellMock->expects($this->never()) + ->method('execute'); $this->assertEquals('3.7', $this->rabbitMq->getVersion()); } - public function testGetVersionNotConfigured() + /** + * @throws ServiceException + */ + public function testGetVersionNotInstalled(): void { $this->environmentMock->expects($this->exactly(3)) ->method('getRelationship') - ->willReturn([]); + ->withConsecutive(['rabbitmq'], ['mq'], ['amqp']) + ->willReturnOnConsecutiveCalls( + [], + [], + [] + ); + $this->shellMock->expects($this->never()) + ->method('execute'); $this->assertEquals('0', $this->rabbitMq->getVersion()); } + + /** + * @param string $version + * @param string $expectedResult + * @throws ServiceException + * + * @dataProvider getVersionFromCliDataProvider + */ + public function testGetVersionFromCli(string $version, string $expectedResult): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with('rabbitmq') + ->willReturn([[ + 'host' => '127.0.0.1', + 'port' => '5672', + ]]); + + $processMock = $this->getMockForAbstractClass(ProcessInterface::class); + $processMock->expects($this->once()) + ->method('getOutput') + ->willReturn($version); + $this->shellMock->expects($this->once()) + ->method('execute') + ->with('dpkg -s rabbitmq-server | grep Version') + ->willReturn($processMock); + + $this->assertEquals($expectedResult, $this->rabbitMq->getVersion()); + } + + /** + * Data provider for testGetVersionFromCli + * @return array + */ + public function getVersionFromCliDataProvider(): array + { + return [ + ['Version: 3.8.5', '3.8'], + ['Version:3.8.5', '3.8'], + ['Version: 111.222.333', '111.222'], + ['Version: some version', '0'], + ['redis_version:abc', '0'], + ['redis:5.3.6', '0'], + ['', '0'], + ['error', '0'], + ]; + } + + public function testGetVersionWithException(): void + { + $exceptionMessage = 'Some shell exception'; + $this->expectException(ServiceException::class); + $this->expectExceptionMessage($exceptionMessage); + + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with('rabbitmq') + ->willReturn([[ + 'host' => '127.0.0.1', + 'port' => '5672', + ]]); + + $this->shellMock->expects($this->once()) + ->method('execute') + ->willThrowException(new ShellException($exceptionMessage)); + $this->rabbitMq->getVersion(); + } } diff --git a/src/Test/Unit/Service/RedisTest.php b/src/Test/Unit/Service/RedisTest.php index ba93f0daf0..7d27c4f2ec 100644 --- a/src/Test/Unit/Service/RedisTest.php +++ b/src/Test/Unit/Service/RedisTest.php @@ -9,6 +9,10 @@ use Magento\MagentoCloud\Config\Environment; use Magento\MagentoCloud\Service\Redis; +use Magento\MagentoCloud\Service\ServiceException; +use Magento\MagentoCloud\Shell\ProcessInterface; +use Magento\MagentoCloud\Shell\ShellException; +use Magento\MagentoCloud\Shell\ShellInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -19,7 +23,7 @@ class RedisTest extends TestCase { /** - * @var Redis|MockObject + * @var Redis */ private $redis; @@ -28,19 +32,26 @@ class RedisTest extends TestCase */ private $environmentMock; + /** + * @var ShellInterface|MockObject + */ + private $shellMock; + /** * @inheritdoc */ public function setUp() { $this->environmentMock = $this->createMock(Environment::class); + $this->shellMock = $this->getMockForAbstractClass(ShellInterface::class); $this->redis = new Redis( - $this->environmentMock + $this->environmentMock, + $this->shellMock ); } - public function testGetConfiguration() + public function testGetConfiguration(): void { $this->environmentMock->expects($this->once()) ->method('getRelationship') @@ -61,7 +72,7 @@ public function testGetConfiguration() ); } - public function testGetSlaveConfiguration() + public function testGetSlaveConfiguration(): void { $this->environmentMock->expects($this->once()) ->method('getRelationship') @@ -82,29 +93,118 @@ public function testGetSlaveConfiguration() ); } - public function testGetVersion() + /** + * @param array $config + * @param string $expectedResult + * @throws \Magento\MagentoCloud\Service\ServiceException + * @throws \ReflectionException + * + * @dataProvider getVersionFromConfigDataProvider + */ + public function testGetVersionFromConfig(array $config, string $expectedResult): void { $this->environmentMock->expects($this->once()) ->method('getRelationship') ->with(Redis::RELATIONSHIP_KEY) - ->willReturn([ - [ + ->willReturn($config); + + $this->shellMock->expects($this->never()) + ->method('execute'); + + $this->assertEquals($expectedResult, $this->redis->getVersion()); + } + + /** + * Data provider for testGetVersionFromConfig + * @return array + */ + public function getVersionFromConfigDataProvider(): array + { + return [ + [ + [[ 'host' => '127.0.0.1', 'port' => '3306', - 'type' => 'mysql:10.2', - ] - ]); + 'type' => 'redis:10.2' + ]], + '10.2' + ], + [ + [[ + 'type' => 'redis:10.2.5' + ]], + '10.2.5' + ], + [ + [], + '0' + ], + ]; + } + + /** + * @param string $version + * @param string $expectedResult + * @throws \Magento\MagentoCloud\Service\ServiceException + * @throws \ReflectionException + * + * @dataProvider getVersionFromCliDataProvider + */ + public function testGetVersionFromCli(string $version, string $expectedResult): void + { + $this->environmentMock->expects($this->once()) + ->method('getRelationship') + ->with(Redis::RELATIONSHIP_KEY) + ->willReturn([[ + 'host' => '127.0.0.1', + 'port' => '3306', + ]]); + + $processMock = $this->getMockForAbstractClass(ProcessInterface::class); + $processMock->expects($this->once()) + ->method('getOutput') + ->willReturn($version); + $this->shellMock->expects($this->once()) + ->method('execute') + ->with('redis-cli -p 3306 -h 127.0.0.1 info | grep redis_version') + ->willReturn($processMock); - $this->assertEquals('10.2', $this->redis->getVersion()); + $this->assertEquals($expectedResult, $this->redis->getVersion()); + } + + /** + * Data provider for testGetVersionFromCli + * @return array + */ + public function getVersionFromCliDataProvider(): array + { + return [ + ['redis_version:5.3.6', '5.3'], + ['redis_version:1.2.3.4.5', '1.2'], + ['redis_version:abc', '0'], + ['redis:5.3.6', '0'], + ['', '0'], + ['error', '0'], + ]; } - public function testGetVersionNotConfigured() + public function testGetVersionWithException() { + $exceptionMessage = 'Some shell exception'; + $this->expectException(ServiceException::class); + $this->expectExceptionMessage($exceptionMessage); + $this->environmentMock->expects($this->once()) ->method('getRelationship') ->with(Redis::RELATIONSHIP_KEY) - ->willReturn([]); + ->willReturn([[ + 'host' => '127.0.0.1', + 'port' => '3306', + ]]); - $this->assertEquals('0', $this->redis->getVersion()); + $this->shellMock->expects($this->once()) + ->method('execute') + ->willThrowException(new ShellException($exceptionMessage)); + $this->redis->getVersion(); } }