diff --git a/.travis.yml b/.travis.yml index e839025535..9151c5edce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ before_install: install: - composer update -n --no-suggest - - ./bin/ece-tools docker:build --test --php ${TRAVIS_PHP_VERSION} + - ./bin/ece-tools docker:build:integration ${TRAVIS_PHP_VERSION} 10.0 latest before_script: docker-compose up -d diff --git a/dist/Makefile b/dist/Makefile index 8d780a4a15..e9dc785c24 100644 --- a/dist/Makefile +++ b/dist/Makefile @@ -1,5 +1,6 @@ .PHONY: help +# https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html help: ## This help @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) diff --git a/src/App/Container.php b/src/App/Container.php index 0ac4e82504..beaf97d75c 100644 --- a/src/App/Container.php +++ b/src/App/Container.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\App; use Magento\MagentoCloud\Command\Build; diff --git a/src/Application.php b/src/Application.php index 82ac7c3677..3e74763d72 100644 --- a/src/Application.php +++ b/src/Application.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud; use Composer\Composer; @@ -70,6 +72,7 @@ protected function getDefaultCommands() $this->container->create(Command\Wizard\IdealState::class), $this->container->create(Command\Wizard\MasterSlave::class), $this->container->create(Command\Docker\Build::class), + $this->container->create(Command\Docker\BuildIntegration::class), $this->container->create(Command\Docker\ConfigConvert::class), $this->container->create(Command\CronKill::class), ] diff --git a/src/Command/Docker/Build.php b/src/Command/Docker/Build.php index 2a53992ff4..333b8a67be 100644 --- a/src/Command/Docker/Build.php +++ b/src/Command/Docker/Build.php @@ -3,14 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Command\Docker; use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\Config\RepositoryFactory; use Magento\MagentoCloud\Docker\BuilderFactory; use Magento\MagentoCloud\Docker\BuilderInterface; use Magento\MagentoCloud\Docker\ConfigurationMismatchException; use Magento\MagentoCloud\Filesystem\Driver\File; -use Magento\MagentoCloud\Filesystem\FileList; use Magento\MagentoCloud\Filesystem\FileSystemException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -31,8 +33,6 @@ class Build extends Command const OPTION_ES = 'es'; const OPTION_RABBIT_MQ = 'rmq'; - const OPTION_IS_TEST = 'test'; - /** * @var BuilderFactory */ @@ -44,31 +44,31 @@ class Build extends Command private $file; /** - * @var FileList + * @var Environment */ - private $fileList; + private $environment; /** - * @var Environment + * @var RepositoryFactory */ - private $environment; + private $configFactory; /** * @param BuilderFactory $builderFactory * @param File $file - * @param FileList $fileList * @param Environment $environment + * @param RepositoryFactory $configFactory */ public function __construct( BuilderFactory $builderFactory, File $file, - FileList $fileList, - Environment $environment + Environment $environment, + RepositoryFactory $configFactory ) { $this->builderFactory = $builderFactory; $this->file = $file; - $this->fileList = $fileList; $this->environment = $environment; + $this->configFactory = $configFactory; parent::__construct(); } @@ -84,47 +84,34 @@ protected function configure() self::OPTION_PHP, null, InputOption::VALUE_OPTIONAL, - 'PHP version', - BuilderInterface::DEFAULT_PHP_VERSION + 'PHP version' )->addOption( self::OPTION_NGINX, null, InputOption::VALUE_OPTIONAL, - 'Nginx version', - BuilderInterface::DEFAULT_NGINX_VERSION + 'Nginx version' )->addOption( self::OPTION_DB, null, InputOption::VALUE_OPTIONAL, - 'DB version', - BuilderInterface::DEFAULT_DB_VERSION + 'DB version' )->addOption( self::OPTION_REDIS, null, InputOption::VALUE_OPTIONAL, - 'Redis version', - BuilderInterface::DEFAULT_REDIS_VERSION + 'Redis version' )->addOption( self::OPTION_ES, null, InputOption::VALUE_OPTIONAL, - 'ElasticSearch version', - BuilderInterface::DEFAULT_ES_VERSION + 'Elasticsearch version' )->addOption( self::OPTION_RABBIT_MQ, null, InputOption::VALUE_OPTIONAL, - 'RabbitMQ version', - BuilderInterface::DEFAULT_RABBIT_MQ_VERSION + 'RabbitMQ version' ); - $this->addOption( - self::OPTION_IS_TEST, - null, - InputOption::VALUE_NONE, - 'Generates ECE-Tools testing configuration (internal usage only)' - ); - parent::configure(); } @@ -136,43 +123,28 @@ protected function configure() */ public function execute(InputInterface $input, OutputInterface $output) { - if ($input->getOption(self::OPTION_IS_TEST)) { - $strategy = BuilderFactory::BUILDER_TEST; - $path = $this->fileList->getToolsDockerCompose(); - } else { - $strategy = BuilderFactory::BUILDER_DEV; - $path = $this->fileList->getMagentoDockerCompose(); - } - - $builder = $this->builderFactory->create($strategy); - - if ($phpVersion = $input->getOption(self::OPTION_PHP)) { - $builder->setPhpVersion($phpVersion); - } - - if ($nginxVersion = $input->getOption(self::OPTION_NGINX)) { - $builder->setNginxVersion($nginxVersion); - } - - if ($dbVersion = $input->getOption(self::OPTION_DB)) { - $builder->setDbVersion($dbVersion); - } - - if ($redisVersion = $input->getOption(self::OPTION_REDIS)) { - $builder->setRedisVersion($redisVersion); - } - - if ($esVersion = $input->getOption(self::OPTION_ES)) { - $builder->setESVersion($esVersion); - } - - if ($rabbitMQVersion = $input->getOption(self::OPTION_RABBIT_MQ)) { - $builder->setRabbitMQVersion($rabbitMQVersion); - } - - $config = Yaml::dump($builder->build(), 4, 2); - - $this->file->filePutContents($path, $config); + $builder = $this->builderFactory->create(BuilderFactory::BUILDER_DEV); + $config = $this->configFactory->create(); + + $map = [ + self::OPTION_PHP => BuilderInterface::PHP_VERSION, + self::OPTION_DB => BuilderInterface::DB_VERSION, + self::OPTION_NGINX => BuilderInterface::NGINX_VERSION, + self::OPTION_REDIS => BuilderInterface::REDIS_VERSION, + self::OPTION_ES => BuilderInterface::ES_VERSION, + self::OPTION_RABBIT_MQ => BuilderInterface::RABBIT_MQ_VERSION, + ]; + + array_walk($map, function ($key, $option) use ($config, $input) { + if ($value = $input->getOption($option)) { + $config->set($key, $value); + } + }); + + $this->file->filePutContents( + $builder->getConfigPath(), + Yaml::dump($builder->build($config), 4, 2) + ); $output->writeln('Configuration was built'); } diff --git a/src/Command/Docker/BuildIntegration.php b/src/Command/Docker/BuildIntegration.php new file mode 100644 index 0000000000..35f875ecf2 --- /dev/null +++ b/src/Command/Docker/BuildIntegration.php @@ -0,0 +1,133 @@ +builderFactory = $builderFactory; + $this->file = $file; + $this->configFactory = $configFactory; + $this->environment = $environment; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure() + { + $this->setName(self::NAME) + ->setDescription('Build test docker configuration') + ->addArgument( + self::ARGUMENT_PHP, + InputArgument::REQUIRED, + 'PHP version' + )->addArgument( + self::ARGUMENT_DB, + InputArgument::REQUIRED, + 'DB version' + )->addArgument( + self::ARGUMENT_NGINX, + InputArgument::REQUIRED, + 'Nginx version' + ); + + parent::configure(); + } + + /** + * {@inheritdoc} + * + * @throws FileSystemException + * @throws ConfigurationMismatchException + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $builder = $this->builderFactory->create(BuilderFactory::BUILDER_TEST); + $config = $this->configFactory->create(); + + $map = [ + self::ARGUMENT_PHP => BuilderInterface::PHP_VERSION, + self::ARGUMENT_DB => BuilderInterface::DB_VERSION, + self::ARGUMENT_NGINX => BuilderInterface::NGINX_VERSION, + ]; + + array_walk($map, function ($key, $option) use ($config, $input) { + $config->set($key, $input->getArgument($option)); + }); + + $this->file->filePutContents( + $builder->getConfigPath(), + Yaml::dump($builder->build($config), 4, 2) + ); + + $output->writeln('Configuration was built'); + } + + /** + * @inheritdoc + */ + public function isEnabled(): bool + { + return !$this->environment->isMasterBranch(); + } +} diff --git a/src/Docker/BuilderInterface.php b/src/Docker/BuilderInterface.php index 8d4f53300e..7bf7b85897 100644 --- a/src/Docker/BuilderInterface.php +++ b/src/Docker/BuilderInterface.php @@ -5,25 +5,13 @@ */ namespace Magento\MagentoCloud\Docker; +use Illuminate\Contracts\Config\Repository; + /** * General Builder interface. */ interface BuilderInterface { - const PHP_VERSIONS = ['7.0', '7.1', '7.2',]; - const DEFAULT_PHP_VERSION = '7.1'; - - const ES_VERSIONS = ['1.7', '2.4', '5.2']; - const DEFAULT_ES_VERSION = '2.4'; - - const RABBIT_MQ_VERSIONS = ['3.5', '3.7']; - const DEFAULT_RABBIT_MQ_VERSION = '3.5'; - const REDIS_VERSIONS = ['3.2', '4.0']; - - const DEFAULT_NGINX_VERSION = 'latest'; - const DEFAULT_DB_VERSION = '10'; - const DEFAULT_REDIS_VERSION = '3.2'; - const PHP_VERSION = 'php.version'; const NGINX_VERSION = 'nginx.version'; const DB_VERSION = 'db.version'; @@ -32,43 +20,14 @@ interface BuilderInterface const RABBIT_MQ_VERSION = 'rmq.version'; /** + * @param Repository $config * @return array - */ - public function build(): array; - - /** - * @param string $version - * @throws ConfigurationMismatchException - */ - public function setPhpVersion(string $version); - - /** - * @param string $version * @throws ConfigurationMismatchException */ - public function setNginxVersion(string $version); + public function build(Repository $config): array; /** - * @param string $version - * @throws ConfigurationMismatchException - */ - public function setDbVersion(string $version); - - /** - * @param string $version - * @throws ConfigurationMismatchException - */ - public function setRedisVersion(string $version); - - /** - * @param string $version - * @throws ConfigurationMismatchException - */ - public function setESVersion(string $version); - - /** - * @param string $version - * @throws ConfigurationMismatchException + * @return string */ - public function setRabbitMQVersion(string $version); + public function getConfigPath(): string; } diff --git a/src/Docker/Config.php b/src/Docker/Config.php new file mode 100644 index 0000000000..18cc1560a0 --- /dev/null +++ b/src/Docker/Config.php @@ -0,0 +1,75 @@ +reader = $reader; + } + + /** + * @return string + * @throws ConfigurationMismatchException + */ + public function getPhpVersion(): string + { + try { + $config = $this->reader->read(); + list($type, $version) = explode(':', $config['type']); + } catch (FileSystemException $exception) { + throw new ConfigurationMismatchException($exception->getMessage(), $exception->getCode(), $exception); + } + + if ($type !== 'php') { + throw new ConfigurationMismatchException(sprintf( + 'Type "%s" is not supported', + $type + )); + } + + /** + * We don't support release candidates. + */ + return rtrim($version, '-rc'); + } + + /** + * @param string $service + * @return string|null + * @throws ConfigurationMismatchException + */ + public function getServiceVersion(string $service) + { + try { + return $this->reader->read()['services'][$service]['version'] ?? null; + } catch (FileSystemException $exception) { + throw new ConfigurationMismatchException($exception->getMessage(), $exception->getCode(), $exception); + } + } +} diff --git a/src/Docker/Config/Reader.php b/src/Docker/Config/Reader.php new file mode 100644 index 0000000000..7d2f3e3ac8 --- /dev/null +++ b/src/Docker/Config/Reader.php @@ -0,0 +1,97 @@ +fileList = $fileList; + $this->file = $file; + } + + /** + * @inheritdoc + */ + public function read(): array + { + try { + $appConfig = Yaml::parse( + $this->file->fileGetContents($this->fileList->getAppConfig()) + ); + $servicesConfig = Yaml::parse( + $this->file->fileGetContents($this->fileList->getServicesConfig()) + ); + } catch (\Exception $exception) { + throw new FileSystemException($exception->getMessage(), $exception->getCode(), $exception); + } + + if (!isset($appConfig['type'])) { + throw new FileSystemException('PHP version could not be parsed.'); + } + + if (!isset($appConfig['relationships'])) { + throw new FileSystemException('Relationships could not be parsed.'); + } + + $config = [ + 'type' => $appConfig['type'], + 'services' => [] + ]; + + foreach ($appConfig['relationships'] as $constraint) { + list($name) = explode(':', $constraint); + + if (!isset($servicesConfig[$name]['type'])) { + throw new FileSystemException(sprintf( + 'Service with name "%s" could not be parsed', + $name + )); + } + + list($service, $version) = explode(':', $servicesConfig[$name]['type']); + + if (array_key_exists($service, $config['services'])) { + throw new FileSystemException(sprintf( + 'Only one instance of service "%s" supported', + $service + )); + } + + $config['services'][$service] = [ + 'service' => $service, + 'version' => $version + ]; + } + + return $config; + } +} diff --git a/src/Docker/DevBuilder.php b/src/Docker/DevBuilder.php index 62667d507a..0f93c647ca 100644 --- a/src/Docker/DevBuilder.php +++ b/src/Docker/DevBuilder.php @@ -3,21 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Docker; use Illuminate\Contracts\Config\Repository; -use Magento\MagentoCloud\Config\RepositoryFactory; use Magento\MagentoCloud\Docker\Service\ServiceFactory; +use Magento\MagentoCloud\Filesystem\FileList; /** * Docker configuration builder. + * + * @codeCoverageIgnore */ class DevBuilder implements BuilderInterface { - /** - * @var Repository - */ - private $config; + const DEFAULT_NGINX_VERSION = 'latest'; + const DEFAULT_VARNISH_VERSION = 'latest'; /** * @var ServiceFactory @@ -25,165 +27,161 @@ class DevBuilder implements BuilderInterface private $serviceFactory; /** - * @param RepositoryFactory $repositoryFactory - * @param ServiceFactory $serviceFactory + * @var FileList */ - public function __construct(RepositoryFactory $repositoryFactory, ServiceFactory $serviceFactory) - { - $this->config = $repositoryFactory->create(); - $this->serviceFactory = $serviceFactory; - } + private $fileList; /** - * @inheritdoc + * @var Config */ - public function setPhpVersion(string $version) - { - $this->setVersion(self::PHP_VERSION, $version, self::PHP_VERSIONS); - } + private $config; /** - * @inheritdoc + * @param ServiceFactory $serviceFactory + * @param FileList $fileList + * @param Config $config */ - public function setNginxVersion(string $version) + public function __construct(ServiceFactory $serviceFactory, FileList $fileList, Config $config) { - $this->setVersion(self::NGINX_VERSION, $version, [ - '1.9', - self::DEFAULT_NGINX_VERSION, - ]); + $this->serviceFactory = $serviceFactory; + $this->fileList = $fileList; + $this->config = $config; } /** - * @inheritdoc + * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function setDbVersion(string $version) + public function build(Repository $config): array { - $this->setVersion(self::DB_VERSION, $version, [ - self::DEFAULT_DB_VERSION, - ]); - } + $phpVersion = $config->get(self::PHP_VERSION, '') ?: $this->config->getPhpVersion(); + $dbVersion = $config->get(self::DB_VERSION, '') ?: $this->config->getServiceVersion(Config::KEY_DB); - /** - * @inheritdoc - */ - public function setRedisVersion(string $version) - { - $this->setVersion(self::REDIS_VERSION, $version, self::REDIS_VERSIONS); - } + $services = [ + 'db' => $this->serviceFactory->create( + ServiceFactory::SERVICE_DB, + $dbVersion, + [ + 'ports' => [3306], + 'volumes' => [ + '/var/lib/mysql', + './docker/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d', + ], + 'environment' => [ + 'MYSQL_ROOT_PASSWORD=magento2', + 'MYSQL_DATABASE=magento2', + 'MYSQL_USER=magento2', + 'MYSQL_PASSWORD=magento2', + ], + ] + ) + ]; - /** - * @inheritdoc - */ - public function setESVersion(string $version) - { - $this->setVersion(self::ES_VERSION, $version, self::ES_VERSIONS); - } + $redisVersion = $config->get(self::REDIS_VERSION) ?: $this->config->getServiceVersion(Config::KEY_REDIS); - /** - * @inheritdoc - */ - public function setRabbitMQVersion(string $version) - { - $this->setVersion(self::RABBIT_MQ_VERSION, $version, self::RABBIT_MQ_VERSIONS); - } + if ($redisVersion) { + $services['redis'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_REDIS, + $redisVersion + ); + } - /** - * @param string $key - * @param string $version - * @param array $supportedVersions - * @throws ConfigurationMismatchException - */ - private function setVersion(string $key, string $version, array $supportedVersions) - { - $parts = explode('.', $key); - $name = reset($parts); + $esVersion = $config->get(self::ES_VERSION) ?: $this->config->getServiceVersion(Config::KEY_ELASTICSEARCH); - if (!\in_array($version, $supportedVersions, true)) { - throw new ConfigurationMismatchException(sprintf( - 'Service %s:%s is not supported', - $name, - $version - )); + if ($esVersion) { + $services['elasticsearch'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_ELASTICSEARCH, + $esVersion + ); } - $this->config->set($key, $version); - } + $rabbitMQVersion = $config->get(self::RABBIT_MQ_VERSION) + ?: $this->config->getServiceVersion(Config::KEY_RABBIT_MQ); - /** - * @return array - */ - public function build(): array - { - return [ - 'version' => '2', - 'services' => [ - 'varnish' => $this->serviceFactory->create(ServiceFactory::SERVICE_VARNISH)->get(), - 'redis' => $this->getRedisService(), - 'elasticsearch' => $this->getElasticSearchService(), - 'rabbitmq' => $this->getRabbitMQService(), - 'fpm' => $this->getFpmService(), - /** For backward compatibility. */ - 'cli' => $this->getCliService(false), - 'build' => $this->getCliService(false), - 'deploy' => $this->getCliService(true), - 'db' => $this->getDbService(), - 'web' => $this->getWebService(), - 'cron' => $this->getCronService(), - 'appdata' => [ - 'image' => 'tianon/true', - 'volumes' => [ - './docker/mnt:/mnt', - '/var/www/magento/vendor', - '/var/www/magento/generated', - '/var/www/magento/pub', - '/var/www/magento/var', - '/var/www/magento/app/etc', - ], + if ($rabbitMQVersion) { + $services['rabbitmq'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_RABBIT_MQ, + $rabbitMQVersion + ); + } + + $cliDepends = array_keys($services); + + $services['varnish'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_VARNISH, + self::DEFAULT_VARNISH_VERSION, + ['depends_on' => ['web']] + ); + $services['fpm'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_FPM, + $phpVersion, + [ + 'ports' => [9000], + 'depends_on' => ['db'], + 'volumes_from' => ['appdata'], + 'volumes' => [$this->getMagentoVolume(false)], + 'env_file' => [ + './docker/global.env', + './docker/config.env', + ], + ] + ); + /** For backward compatibility. */ + $services['cli'] = $this->getCliService($phpVersion, false, $cliDepends); + $services['build'] = $this->getCliService($phpVersion, false, $cliDepends); + $services['deploy'] = $this->getCliService($phpVersion, true, $cliDepends); + $services['web'] = $this->serviceFactory->create( + ServiceFactory::SERVICE_NGINX, + $config->get(self::NGINX_VERSION, self::DEFAULT_NGINX_VERSION), + [ + 'ports' => [ + '8080:80', + '443:443', + ], + 'depends_on' => [ + 'fpm', + 'db', + ], + 'volumes_from' => [ + 'appdata', + ], + 'volumes' => [ + $this->getMagentoVolume(false), ], + 'env_file' => [ + './docker/global.env', + './docker/config.env', + ], + ] + ); + $services['cron'] = $this->getCliService($phpVersion, true, $cliDepends, true); + $services['appdata'] = [ + 'image' => 'tianon/true', + 'volumes' => [ + './docker/mnt:/mnt', + '/var/www/magento/vendor', + '/var/www/magento/generated', + '/var/www/magento/pub', + '/var/www/magento/var', + '/var/www/magento/app/etc', ], ]; - } - - /** - * @return array - */ - private function getElasticSearchService(): array - { - $version = $this->config->get(self::ES_VERSION, self::DEFAULT_ES_VERSION); - - return [ - 'image' => sprintf('%s:%s', 'magento/magento-cloud-docker-elasticsearch', $version), - ]; - } - - /** - * @return array - */ - private function getRabbitMQService(): array - { - $version = $this->config->get(self::RABBIT_MQ_VERSION, self::DEFAULT_RABBIT_MQ_VERSION); return [ - 'image' => sprintf('rabbitmq:%s', $version) + 'version' => '2', + 'services' => $services, ]; } /** - * @return array + * @return string */ - private function getRedisService(): array + public function getConfigPath(): string { - $version = $this->config->get(self::REDIS_VERSION, self::DEFAULT_REDIS_VERSION); - - return [ - 'image' => 'redis:' . $version, - 'volumes' => [ - '/data', - ], - 'ports' => [ - 6379, - ], - ]; + return $this->fileList->getMagentoDockerCompose(); } /** @@ -200,135 +198,42 @@ private function getMagentoVolume(bool $isReadOnly): string } /** - * @return array - */ - private function getFpmService(): array - { - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-php:%s-fpm', - $this->config->get(self::PHP_VERSION, self::DEFAULT_PHP_VERSION) - ), - 'ports' => [ - 9000, - ], - 'depends_on' => [ - 'db', - ], - 'volumes_from' => [ - 'appdata', - ], - 'volumes' => [ - $this->getMagentoVolume(false), - ], - 'env_file' => [ - './docker/global.env', - './docker/config.env', - ], - ]; - } - - /** + * @param string $version * @param bool $isReadOnly + * @param array $depends + * @param bool $cron * @return array + * @throws ConfigurationMismatchException */ - private function getCliService(bool $isReadOnly): array - { - if (file_exists(getenv('HOME') . '/.cache/composer')) { - $composeCacheDirectory = '~/.cache/composer'; - } else { - $composeCacheDirectory = '~/.composer/cache'; - } - - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-php:%s-cli', - $this->config->get(self::PHP_VERSION, self::DEFAULT_PHP_VERSION) - ), - 'depends_on' => [ - 'db', - 'redis', - 'elasticsearch' - ], - 'volumes' => [ - $composeCacheDirectory . ':/root/.composer/cache', - $this->getMagentoVolume($isReadOnly), - ], - 'volumes_from' => [ - 'appdata', - ], - 'env_file' => [ - './docker/global.env', - './docker/config.env', - ], - ]; - } - - /** - * @return array - */ - private function getDbService(): array + private function getCliService(string $version, bool $isReadOnly, array $depends, bool $cron = false): array { - return [ - 'image' => sprintf( - 'mariadb:%s', - $this->config->get(self::DB_VERSION, self::DEFAULT_DB_VERSION) - ), - 'ports' => [ - 3306, - ], - 'volumes' => [ - '/var/lib/mysql', - './docker/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d', - ], - 'environment' => [ - 'MYSQL_ROOT_PASSWORD=magento2', - 'MYSQL_DATABASE=magento2', - 'MYSQL_USER=magento2', - 'MYSQL_PASSWORD=magento2', - ], - ]; - } + $composeCacheDirectory = file_exists(getenv('HOME') . '/.cache/composer') + ? '~/.cache/composer' + : '~/.composer/cache'; - /** - * @return array - */ - private function getWebService(): array - { - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-nginx:%s', - $this->config->get(self::NGINX_VERSION, self::DEFAULT_NGINX_VERSION) - ), - 'ports' => [ - '8080:80', - '443:443', - ], - 'depends_on' => [ - 'fpm', - 'db', - ], - 'volumes_from' => [ - 'appdata', - ], - 'volumes' => [ - $this->getMagentoVolume(false), - ], - 'env_file' => [ - './docker/global.env', - './docker/config.env', - ], - ]; - } + $config = $this->serviceFactory->create( + ServiceFactory::SERVICE_CLI, + $version, + [ + 'depends_on' => $depends, + 'volumes' => [ + $composeCacheDirectory . ':/root/.composer/cache', + $this->getMagentoVolume($isReadOnly), + ], + 'volumes_from' => [ + 'appdata', + ], + 'env_file' => [ + './docker/global.env', + './docker/config.env', + ], + ] + ); - /** - * @return array - */ - private function getCronService(): array - { - $cliService = $this->getCliService(true); - $cliService['command'] = 'run-cron'; + if ($cron) { + $config['command'] = 'run-cron'; + } - return $cliService; + return $config; } } diff --git a/src/Docker/IntegrationBuilder.php b/src/Docker/IntegrationBuilder.php index b87c2e080c..4a4df9179d 100644 --- a/src/Docker/IntegrationBuilder.php +++ b/src/Docker/IntegrationBuilder.php @@ -3,119 +3,125 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Docker; use Illuminate\Contracts\Config\Repository; -use Magento\MagentoCloud\Config\RepositoryFactory; +use Magento\MagentoCloud\Docker\Service\ServiceFactory; +use Magento\MagentoCloud\Filesystem\FileList; /** - * @inheritdoc + * Docker integration test builder. + * + * @codeCoverageIgnore */ class IntegrationBuilder implements BuilderInterface { /** - * @var Repository - */ - private $config; - - /** - * @param RepositoryFactory $repositoryFactory - */ - public function __construct(RepositoryFactory $repositoryFactory) - { - $this->config = $repositoryFactory->create(); - } - - /** - * @inheritdoc + * @var FileList */ - public function setPhpVersion(string $version) - { - $this->setVersion(self::PHP_VERSION, $version, self::PHP_VERSIONS); - } + private $fileList; /** - * @inheritdoc + * @var ServiceFactory */ - public function setRabbitMQVersion(string $version) - { - $this->setVersion(self::RABBIT_MQ_VERSION, $version, self::RABBIT_MQ_VERSIONS); - } + private $factory; /** - * @inheritdoc + * @param FileList $fileList + * @param ServiceFactory $serviceFactory */ - public function setESVersion(string $version) + public function __construct(FileList $fileList, ServiceFactory $serviceFactory) { - $this->setVersion(self::ES_VERSION, $version, self::ES_VERSIONS); + $this->fileList = $fileList; + $this->factory = $serviceFactory; } /** * @inheritdoc */ - public function setDbVersion(string $version) - { - $this->setVersion(self::DB_VERSION, $version, [ - self::DEFAULT_DB_VERSION, - ]); - } - - /** - * @param string $version - * @throws ConfigurationMismatchException - */ - public function setRedisVersion(string $version) - { - $this->setVersion(self::REDIS_VERSION, $version, [ - self::DEFAULT_REDIS_VERSION, - ]); - } - - /** - * @inheritdoc - */ - public function setNginxVersion(string $version) - { - $this->setVersion(self::NGINX_VERSION, $version, [ - '1.9', - self::DEFAULT_NGINX_VERSION, - ]); - } - - /** - * @param string $key - * @param string $version - * @param array $supportedVersions - * @throws ConfigurationMismatchException - */ - private function setVersion(string $key, string $version, array $supportedVersions) - { - $parts = explode('.', $key); - $name = reset($parts); - - if (!\in_array($version, $supportedVersions, true)) { - throw new ConfigurationMismatchException(sprintf( - 'Service %s:%s is not supported', - $name, - $version - )); - } - - $this->config->set($key, $version); - } - - /** - * @return array - */ - public function build(): array + public function build(Repository $repository): array { return [ 'version' => '2', 'services' => [ - 'fpm' => $this->getFpmService(), - 'cli' => $this->getCliService(), - 'db' => $this->getDbService(), - 'web' => $this->getWebService(), + 'cli' => $this->factory->create( + ServiceFactory::SERVICE_CLI, + $repository->get(self::PHP_VERSION), + [ + 'links' => [ + 'db', + ], + 'volumes' => [ + '~/.composer/cache:/root/.composer/cache', + ], + 'volumes_from' => [ + 'appdata', + ], + 'env_file' => [ + './docker/global.env', + './docker/composer.env', + ] + ] + ), + 'fpm' => $this->factory->create( + ServiceFactory::SERVICE_FPM, + $repository->get(self::PHP_VERSION), + [ + 'ports' => [ + 9000, + ], + 'links' => [ + 'db', + ], + 'volumes_from' => [ + 'appdata', + ], + 'env_file' => [ + './docker/global.env', + './docker/composer.env', + ], + ] + ), + 'db' => $this->factory->create( + ServiceFactory::SERVICE_DB, + $repository->get(self::DB_VERSION), + [ + 'ports' => [ + 3306, + ], + 'volumes' => [ + '/var/lib/mysql', + ], + 'environment' => [ + 'MYSQL_ROOT_PASSWORD=magento2', + 'MYSQL_DATABASE=magento2', + 'MYSQL_USER=magento2', + 'MYSQL_PASSWORD=magento2', + ], + ] + ), + 'web' => $this->factory->create( + ServiceFactory::SERVICE_NGINX, + $repository->get(self::NGINX_VERSION), + [ + 'ports' => [ + '8080:80', + ], + 'links' => [ + 'fpm', + 'db', + ], + 'volumes_from' => [ + 'appdata', + ], + 'env_file' => [ + './docker/global.env', + './docker/composer.env', + ], + ] + ), 'appdata' => [ 'image' => 'tianon/true', 'volumes' => [ @@ -128,106 +134,10 @@ public function build(): array } /** - * @return array - */ - private function getFpmService(): array - { - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-php:%s-fpm', - $this->config->get(self::PHP_VERSION, self::DEFAULT_PHP_VERSION) - ), - 'ports' => [ - 9000, - ], - 'links' => [ - 'db', - ], - 'volumes_from' => [ - 'appdata', - ], - 'env_file' => [ - './docker/global.env', - './docker/composer.env', - ], - ]; - } - - /** - * @return array - */ - private function getCliService(): array - { - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-php:%s-cli', - $this->config->get(self::PHP_VERSION, self::DEFAULT_PHP_VERSION) - ), - 'links' => [ - 'db', - ], - 'volumes' => [ - '~/.composer/cache:/root/.composer/cache', - ], - 'volumes_from' => [ - 'appdata', - ], - 'env_file' => [ - './docker/global.env', - './docker/composer.env', - ] - ]; - } - - /** - * @return array - */ - private function getDbService(): array - { - return [ - 'image' => sprintf( - 'mariadb:%s', - $this->config->get(self::DB_VERSION, self::DEFAULT_DB_VERSION) - ), - 'ports' => [ - 3306, - ], - 'volumes' => [ - '/var/lib/mysql', - ], - 'environment' => [ - 'MYSQL_ROOT_PASSWORD=magento2', - 'MYSQL_DATABASE=magento2', - 'MYSQL_USER=magento2', - 'MYSQL_PASSWORD=magento2', - ], - ]; - } - - /** - * @return array + * @inheritdoc */ - private function getWebService(): array + public function getConfigPath(): string { - return [ - 'image' => sprintf( - 'magento/magento-cloud-docker-nginx:%s', - $this->config->get(self::NGINX_VERSION, self::DEFAULT_NGINX_VERSION) - ), - 'ports' => [ - '8080:80', - ], - 'links' => [ - 'fpm', - 'db', - ], - 'volumes_from' => [ - 'appdata', - ], - 'env_file' => [ - './docker/global.env', - './docker/composer.env', - ], - ]; + return $this->fileList->getToolsDockerCompose(); } } diff --git a/src/Docker/Service/ServiceFactory.php b/src/Docker/Service/ServiceFactory.php index 6ee9fa4880..9cb9d1dd77 100644 --- a/src/Docker/Service/ServiceFactory.php +++ b/src/Docker/Service/ServiceFactory.php @@ -3,45 +3,110 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Docker\Service; -use Magento\MagentoCloud\App\ContainerInterface; +use Magento\MagentoCloud\Docker\ConfigurationMismatchException; /** * Create instance of Docker service configuration. */ class ServiceFactory { + const SERVICE_CLI = 'php-cli'; + const SERVICE_FPM = 'php-fpm'; + const SERVICE_REDIS = 'redis'; + const SERVICE_DB = 'db'; + const SERVICE_NGINX = 'nginx'; const SERVICE_VARNISH = 'varnish'; - const SERVICE_RABBITMQ = 'rabbitmq'; + const SERVICE_ELASTICSEARCH = 'elasticsearch'; + const SERVICE_RABBIT_MQ = 'rabbitmq'; - /** - * @var array - */ - private static $map = [ - self::SERVICE_VARNISH => VarnishService::class, - self::SERVICE_RABBITMQ => RabbitMqService::class, + const CONFIG = [ + self::SERVICE_CLI => [ + 'image' => 'magento/magento-cloud-docker-php:%s-cli', + 'versions' => ['7.0', '7.1', '7.2'] + ], + self::SERVICE_FPM => [ + 'image' => 'magento/magento-cloud-docker-php:%s-fpm', + 'versions' => ['7.0', '7.1', '7.2'] + ], + self::SERVICE_DB => [ + 'image' => 'mariadb:%s', + 'versions' => ['10.0', '10.1', '10.2'] + ], + self::SERVICE_NGINX => [ + 'image' => 'magento/magento-cloud-docker-nginx:%s', + 'versions' => ['1.9', 'latest'] + ], + self::SERVICE_VARNISH => [ + 'image' => 'magento/magento-cloud-docker-varnish:%s', + 'versions' => ['latest'], + 'config' => [ + 'environment' => [ + 'VIRTUAL_HOST' => 'magento2.docker', + 'VIRTUAL_PORT' => 80, + 'HTTPS_METHOD' => 'noredirect', + ], + 'ports' => [ + '80:80', + ], + ] + ], + self::SERVICE_REDIS => [ + 'image' => 'redis:%s', + 'versions' => ['3.0', '3.2', '4.0'], + 'config' => [ + 'volumes' => [ + '/data', + ], + 'ports' => [ + 6379, + ], + ] + ], + self::SERVICE_ELASTICSEARCH => [ + 'image' => 'magento/magento-cloud-docker-elasticsearch:%s', + 'versions' => ['1.7', '2.4', '5.2'] + ], + self::SERVICE_RABBIT_MQ => [ + 'image' => 'rabbitmq:%s', + 'versions' => ['3.5', '3.7'] + ], ]; - /** - * @var ContainerInterface - */ - private $container; - - /** - * @param ContainerInterface $container - */ - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - /** * @param string $name - * @return ServiceInterface + * @param string $version + * @param array $extendedConfig + * @return array + * @throws ConfigurationMismatchException */ - public function create(string $name): ServiceInterface + public function create(string $name, string $version, array $extendedConfig = []): array { - return $this->container->create(self::$map[$name]); + if (!array_key_exists($name, self::CONFIG)) { + throw new ConfigurationMismatchException(sprintf( + 'Service "%s" is not supported', + $name + )); + } + + $metaConfig = self::CONFIG[$name]; + $defaultConfig = $metaConfig['config'] ?? []; + + if (!in_array($version, $metaConfig['versions'], true)) { + throw new ConfigurationMismatchException(sprintf( + 'Service "%s" does not support version "%s"', + $name, + $version + )); + } + + return array_replace( + ['image' => sprintf($metaConfig['image'], $version)], + $defaultConfig, + $extendedConfig + ); } } diff --git a/src/Docker/Service/ServiceInterface.php b/src/Docker/Service/ServiceInterface.php deleted file mode 100644 index e86c4c3741..0000000000 --- a/src/Docker/Service/ServiceInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - 'magento/magento-cloud-docker-varnish:latest', - 'environment' => [ - 'VIRTUAL_HOST' => 'magento2.docker', - 'VIRTUAL_PORT' => 80, - 'HTTPS_METHOD' => 'noredirect', - ], - 'ports' => [ - '80:80', - ], - 'depends_on' => [ - 'web', - ], - ]; - } -} diff --git a/src/Filesystem/FileList.php b/src/Filesystem/FileList.php index 6f494d3459..e25bf37111 100644 --- a/src/Filesystem/FileList.php +++ b/src/Filesystem/FileList.php @@ -81,4 +81,20 @@ public function getToolsDockerCompose(): string { return $this->directoryList->getRoot() . '/docker-compose.yml'; } + + /** + * @return string + */ + public function getAppConfig(): string + { + return $this->directoryList->getMagentoRoot() . '/.magento.app.yaml'; + } + + /** + * @return string + */ + public function getServicesConfig(): string + { + return $this->directoryList->getMagentoRoot() . '/.magento/services.yaml'; + } } diff --git a/src/Filesystem/Reader/ReaderInterface.php b/src/Filesystem/Reader/ReaderInterface.php index 62b4b0439c..39c1c06189 100644 --- a/src/Filesystem/Reader/ReaderInterface.php +++ b/src/Filesystem/Reader/ReaderInterface.php @@ -5,6 +5,8 @@ */ namespace Magento\MagentoCloud\Filesystem\Reader; +use Magento\MagentoCloud\Filesystem\FileSystemException; + /** * Read content of file. */ @@ -12,6 +14,7 @@ interface ReaderInterface { /** * @return array + * @throws FileSystemException */ public function read(): array; } diff --git a/src/Test/Unit/ApplicationTest.php b/src/Test/Unit/ApplicationTest.php index f2d3f428e3..74aca3daf8 100644 --- a/src/Test/Unit/ApplicationTest.php +++ b/src/Test/Unit/ApplicationTest.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Test\Unit; use Composer\Composer; @@ -73,6 +75,7 @@ class ApplicationTest extends TestCase Command\Wizard\IdealState::NAME => Command\Wizard\IdealState::class, Command\Wizard\MasterSlave::NAME => Command\Wizard\MasterSlave::class, Command\Docker\Build::NAME => Command\Docker\Build::class, + Command\Docker\BuildIntegration::NAME => Command\Docker\BuildIntegration::class, Command\Docker\ConfigConvert::NAME => Command\Docker\ConfigConvert::class, Command\CronKill::NAME => Command\CronKill::class, ]; diff --git a/src/Test/Unit/Command/BuildTest.php b/src/Test/Unit/Command/BuildTest.php new file mode 100644 index 0000000000..3df51f261e --- /dev/null +++ b/src/Test/Unit/Command/BuildTest.php @@ -0,0 +1,58 @@ +command = new Build(); + } + + /** + * @inheritdoc + */ + public function testExecute() + { + /** @var InputInterface|MockObject $inputMock */ + $inputMock = $this->createMock(InputInterface::class); + /** @var OutputInterface|MockObject $outputMock */ + $outputMock = $this->createMock(OutputInterface::class); + /** @var Application|MockObject $applicationMock */ + $applicationMock = $this->createMock(Application::class); + + $applicationMock->method('getHelperSet') + ->willReturn($this->createMock(HelperSet::class)); + $applicationMock->expects($this->exactly(2)) + ->method('find') + ->willReturnMap([ + [Build\Generate::NAME, $this->createMock(Build\Generate::class)], + [Build\Transfer::NAME, $this->createMock(Build\Transfer::class)], + ]); + + $this->command->setApplication($applicationMock); + $this->command->execute($inputMock, $outputMock); + } +} diff --git a/src/Test/Unit/Command/Docker/BuildIntegrationTest.php b/src/Test/Unit/Command/Docker/BuildIntegrationTest.php new file mode 100644 index 0000000000..9bc282b58d --- /dev/null +++ b/src/Test/Unit/Command/Docker/BuildIntegrationTest.php @@ -0,0 +1,136 @@ +builderFactoryMock = $this->createMock(BuilderFactory::class); + $this->fileMock = $this->createMock(File::class); + $this->configFactoryMock = $this->createMock(RepositoryFactory::class); + $this->builderMock = $this->getMockForAbstractClass(BuilderInterface::class); + $this->configMock = $this->getMockForAbstractClass(Repository::class); + $this->environmentMock = $this->createMock(Environment::class); + + $this->configFactoryMock->method('create') + ->willReturn($this->configMock); + + $this->command = new BuildIntegration( + $this->builderFactoryMock, + $this->fileMock, + $this->configFactoryMock, + $this->environmentMock + ); + } + + /** + * @throws ConfigurationMismatchException + * @throws FileSystemException + */ + public function testExecute() + { + /** @var InputInterface|MockObject $inputMock */ + $inputMock = $this->getMockForAbstractClass(InputInterface::class); + /** @var OutputInterface|MockObject $outputMock */ + $outputMock = $this->getMockForAbstractClass(OutputInterface::class); + + $this->builderFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->builderMock); + $this->builderMock->expects($this->once()) + ->method('build') + ->willReturn(['version' => '2']); + $this->fileMock->expects($this->once()) + ->method('filePutContents') + ->with('magento_root/docker-compose.yml', "version: '2'\n"); + $inputMock->method('getArgument') + ->willReturnMap([ + [BuildIntegration::ARGUMENT_PHP, '7.1'], + [BuildIntegration::ARGUMENT_DB, '10.0'], + [BuildIntegration::ARGUMENT_NGINX, '1.9'], + ]); + $this->builderMock->expects($this->once()) + ->method('getConfigPath') + ->willReturn('magento_root/docker-compose.yml'); + $this->configMock->expects($this->exactly(3)) + ->method('set') + ->withConsecutive( + [BuilderInterface::PHP_VERSION, '7.1'], + [BuilderInterface::DB_VERSION, '10.0'], + [BuilderInterface::NGINX_VERSION, '1.9'] + ); + + $this->command->execute($inputMock, $outputMock); + } + + public function testIsEnabled() + { + $this->environmentMock->expects($this->exactly(2)) + ->method('isMasterBranch') + ->willReturnOnConsecutiveCalls(true, false); + + $this->assertFalse($this->command->isEnabled()); + $this->assertTrue($this->command->isEnabled()); + } +} diff --git a/src/Test/Unit/Command/Docker/BuildTest.php b/src/Test/Unit/Command/Docker/BuildTest.php index 9d4a8bac58..11ebcfd691 100644 --- a/src/Test/Unit/Command/Docker/BuildTest.php +++ b/src/Test/Unit/Command/Docker/BuildTest.php @@ -3,14 +3,19 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Test\Unit\Command\Docker; +use Illuminate\Config\Repository; use Magento\MagentoCloud\Command\Docker\Build; use Magento\MagentoCloud\Config\Environment; +use Magento\MagentoCloud\Config\RepositoryFactory; use Magento\MagentoCloud\Docker\BuilderFactory; +use Magento\MagentoCloud\Docker\ConfigurationMismatchException; use Magento\MagentoCloud\Docker\DevBuilder; use Magento\MagentoCloud\Filesystem\Driver\File; -use Magento\MagentoCloud\Filesystem\FileList; +use Magento\MagentoCloud\Filesystem\FileSystemException; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\InputInterface; @@ -42,14 +47,19 @@ class BuildTest extends TestCase private $fileMock; /** - * @var FileList|MockObject + * @var Environment|MockObject */ - private $fileListMock; + private $environmentMock; /** - * @var Environment|MockObject + * @var RepositoryFactory|MockObject */ - private $environmentMock; + private $repositoryFactoryMock; + + /** + * @var Repository|MockObject + */ + private $configMock; /** * @inheritdoc @@ -58,82 +68,69 @@ protected function setUp() { $this->builderFactoryMock = $this->createMock(BuilderFactory::class); $this->builderMock = $this->createMock(DevBuilder::class); - $this->fileListMock = $this->createMock(FileList::class); $this->fileMock = $this->createMock(File::class); $this->environmentMock = $this->createMock(Environment::class); + $this->repositoryFactoryMock = $this->createMock(RepositoryFactory::class); + $this->configMock = $this->createMock(Repository::class); + + $this->repositoryFactoryMock->method('create') + ->willReturn($this->configMock); $this->command = new Build( $this->builderFactoryMock, $this->fileMock, - $this->fileListMock, - $this->environmentMock + $this->environmentMock, + $this->repositoryFactoryMock ); } + /** + * @throws ConfigurationMismatchException + * @throws FileSystemException + */ public function testExecute() { + /** @var InputInterface $inputMock */ $inputMock = $this->getMockForAbstractClass(InputInterface::class); + /** @var OutputInterface $outputMock */ $outputMock = $this->getMockForAbstractClass(OutputInterface::class); $this->builderFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->builderMock); - $this->fileListMock->expects($this->once()) - ->method('getMagentoDockerCompose') - ->willReturn('magento_root/docker-compose.yml'); $this->builderMock->expects($this->once()) ->method('build') ->willReturn(['version' => '2']); - $this->fileMock->expects($this->once()) - ->method('filePutContents') - ->with('magento_root/docker-compose.yml', "version: '2'\n"); - - $this->command->execute($inputMock, $outputMock); - } - - public function testExecuteTestSet() - { - $inputMock = $this->getMockForAbstractClass(InputInterface::class); - $outputMock = $this->getMockForAbstractClass(OutputInterface::class); - - $inputMock->method('getOption') - ->willReturnMap([ - [Build::OPTION_IS_TEST, true], - ]); - - $this->builderFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->builderMock); - $this->fileListMock->expects($this->once()) - ->method('getToolsDockerCompose') - ->willReturn('ece_root/docker-compose.yml'); $this->builderMock->expects($this->once()) - ->method('build') - ->willReturn(['version' => '2']); + ->method('getConfigPath') + ->willReturn('magento_root/docker-compose.yml'); $this->fileMock->expects($this->once()) ->method('filePutContents') - ->with('ece_root/docker-compose.yml', "version: '2'\n"); + ->with('magento_root/docker-compose.yml', "version: '2'\n"); $this->command->execute($inputMock, $outputMock); } + /** + * @throws ConfigurationMismatchException + * @throws FileSystemException + */ public function testExecuteWithParams() { + /** @var InputInterface|MockObject $inputMock */ $inputMock = $this->getMockForAbstractClass(InputInterface::class); + /** @var OutputInterface|MockObject $outputMock */ $outputMock = $this->getMockForAbstractClass(OutputInterface::class); $this->builderFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->builderMock); - $this->fileListMock->expects($this->once()) - ->method('getMagentoDockerCompose') - ->willReturn('magento_rood/docker-compose.yml'); $this->builderMock->expects($this->once()) ->method('build') ->willReturn(['version' => '2']); $this->fileMock->expects($this->once()) ->method('filePutContents') - ->with('magento_rood/docker-compose.yml', "version: '2'\n"); + ->with('magento_root/docker-compose.yml', "version: '2'\n"); $inputMock->method('getOption') ->willReturnMap([ [Build::OPTION_PHP, '7.1'], @@ -141,27 +138,13 @@ public function testExecuteWithParams() [Build::OPTION_NGINX, '1.9'], [Build::OPTION_REDIS, '3.2'], [Build::OPTION_ES, '2.4'], - [Build::OPTION_RABBIT_MQ, '3.5'], - [Build::OPTION_IS_TEST, false], + [Build::OPTION_RABBIT_MQ, '3.5'] ]); $this->builderMock->expects($this->once()) - ->method('setPhpVersion') - ->with('7.1'); - $this->builderMock->expects($this->once()) - ->method('setNginxVersion') - ->with('1.9'); - $this->builderMock->expects($this->once()) - ->method('setRedisVersion') - ->with('3.2'); - $this->builderMock->expects($this->once()) - ->method('setDbVersion') - ->with('10'); - $this->builderMock->expects($this->once()) - ->method('setESVersion') - ->with('2.4'); - $this->builderMock->expects($this->once()) - ->method('setRabbitMQVersion') - ->with('3.5'); + ->method('getConfigPath') + ->willReturn('magento_root/docker-compose.yml'); + $this->configMock->expects($this->exactly(6)) + ->method('set'); $this->command->execute($inputMock, $outputMock); } diff --git a/src/Test/Unit/Config/Application/HookCheckerTest.php b/src/Test/Unit/Config/Application/HookCheckerTest.php index b14d7aac89..5a5f197b1b 100644 --- a/src/Test/Unit/Config/Application/HookCheckerTest.php +++ b/src/Test/Unit/Config/Application/HookCheckerTest.php @@ -6,7 +6,6 @@ namespace Magento\MagentoCloud\Test\Unit\Config\Application; use Magento\MagentoCloud\Config\Application\HookChecker; -use Magento\MagentoCloud\Config\Application\Reader; use Magento\MagentoCloud\Config\Environment; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/src/Test/Unit/Docker/Config/ReaderTest.php b/src/Test/Unit/Docker/Config/ReaderTest.php new file mode 100644 index 0000000000..5556046300 --- /dev/null +++ b/src/Test/Unit/Docker/Config/ReaderTest.php @@ -0,0 +1,285 @@ +fileListMock = $this->createMock(FileList::class); + $this->fileMock = $this->createMock(File::class); + + $this->fileListMock->method('getAppConfig') + ->willReturn('/root/.magento.app.yaml'); + $this->fileListMock->method('getServicesConfig') + ->willReturn('/root/.magento/services.yaml'); + + $this->reader = new Reader( + $this->fileListMock, + $this->fileMock + ); + } + + /** + * @expectedException \Magento\MagentoCloud\Filesystem\FileSystemException + * @expectedExceptionMessage PHP version could not be parsed. + * + * @throws FileSystemException + */ + public function testReadEmpty() + { + $this->fileMock->expects($this->exactly(2)) + ->method('fileGetContents') + ->willReturn(Yaml::dump([])); + + $this->reader->read(); + } + + /** + * @expectedException \Magento\MagentoCloud\Filesystem\FileSystemException + * @expectedExceptionMessage Relationships could not be parsed. + * + * @throws FileSystemException + */ + public function testReadWithPhp() + { + $this->fileMock->expects($this->exactly(2)) + ->method('fileGetContents') + ->willReturnMap([ + ['/root/.magento.app.yaml', null, null, Yaml::dump(['type' => 'php:7.1'])], + ['/root/.magento/services.yaml', null, null, Yaml::dump([])] + ]); + + $this->reader->read(); + } + + /** + * @expectedExceptionMessage Only one instance of service "elasticsearch" supported + * @expectedException \Magento\MagentoCloud\Filesystem\FileSystemException + * + * @throws FileSystemException + */ + public function testReadWithMultipleSameServices() + { + $this->fileMock->expects($this->exactly(2)) + ->method('fileGetContents') + ->willReturnMap([ + [ + '/root/.magento.app.yaml', + null, + null, + Yaml::dump([ + 'type' => 'php:7.1', + 'relationships' => [ + 'database' => 'mysql:mysql', + 'elasticsearch' => 'elasticsearch:elasticsearch', + 'elasticsearch5' => 'elasticsearch5:elasticsearch' + ] + ]), + ], + [ + '/root/.magento/services.yaml', + null, + null, + Yaml::dump([ + 'mysql' => [ + 'type' => 'mysql:10.0', + 'disk' => '2048' + ], + 'elasticsearch' => [ + 'type' => 'elasticsearch:1.4', + 'disk' => '1024' + ], + 'elasticsearch5' => [ + 'type' => 'elasticsearch:5.2', + 'disk' => '1024' + ] + ]) + ] + ]); + + $this->assertSame([ + 'type' => 'php:7.1', + 'services' => [ + 'mysql' => [ + 'service' => 'mysql', + 'version' => '10.0' + ], + 'redis' => [ + 'service' => 'redis', + 'version' => '3.0' + ], + 'elasticsearch' => [ + 'service' => 'elasticsearch', + 'version' => '1.4' + ], + 'rabbitmq' => [ + 'service' => 'rabbitmq', + 'version' => '3.5' + ] + ] + ], $this->reader->read()); + } + + /** + * @expectedExceptionMessage Service with name "myrabbitmq" could not be parsed + * @expectedException \Magento\MagentoCloud\Filesystem\FileSystemException + * + * @throws FileSystemException + */ + public function testReadWithMissedService() + { + $this->fileMock->expects($this->exactly(2)) + ->method('fileGetContents') + ->willReturnMap([ + [ + '/root/.magento.app.yaml', + null, + null, + Yaml::dump([ + 'type' => 'php:7.1', + 'relationships' => [ + 'database' => 'mysql:mysql', + 'elasticsearch' => 'elasticsearch:elasticsearch', + 'mq' => 'myrabbitmq:rabbitmq' + ] + ]), + ], + [ + '/root/.magento/services.yaml', + null, + null, + Yaml::dump([ + 'mysql' => [ + 'type' => 'mysql:10.0', + 'disk' => '2048' + ], + 'elasticsearch' => [ + 'type' => 'elasticsearch:1.4', + 'disk' => '1024' + ], + ]) + ] + ]); + + $this->reader->read(); + } + + /** + * @expectedException \Magento\MagentoCloud\Filesystem\FileSystemException + * @expectedExceptionMessage Some error + * + * @throws FileSystemException + */ + public function testReadBroken() + { + $this->fileListMock->expects($this->once()) + ->method('getAppConfig') + ->willThrowException(new \Exception('Some error')); + + $this->reader->read(); + } + + /** + * @throws FileSystemException + */ + public function testRead() + { + $this->fileMock->expects($this->exactly(2)) + ->method('fileGetContents') + ->willReturnMap([ + [ + '/root/.magento.app.yaml', + null, + null, + Yaml::dump([ + 'type' => 'php:7.1', + 'relationships' => [ + 'database' => 'mysql:mysql', + 'redis' => 'redis:redis', + 'elasticsearch' => 'elasticsearch:elasticsearch', + 'mq' => 'myrabbitmq:rabbitmq' + ] + ]), + ], + [ + '/root/.magento/services.yaml', + null, + null, + Yaml::dump([ + 'mysql' => [ + 'type' => 'mysql:10.0', + 'disk' => '2048' + ], + 'redis' => [ + 'type' => 'redis:3.0' + ], + 'elasticsearch' => [ + 'type' => 'elasticsearch:1.4', + 'disk' => '1024' + ], + 'myrabbitmq' => [ + 'type' => 'rabbitmq:3.5', + 'disk' => '1024' + ] + ]) + ] + ]); + + $this->assertSame([ + 'type' => 'php:7.1', + 'services' => [ + 'mysql' => [ + 'service' => 'mysql', + 'version' => '10.0' + ], + 'redis' => [ + 'service' => 'redis', + 'version' => '3.0' + ], + 'elasticsearch' => [ + 'service' => 'elasticsearch', + 'version' => '1.4' + ], + 'rabbitmq' => [ + 'service' => 'rabbitmq', + 'version' => '3.5' + ] + ] + ], $this->reader->read()); + } +} diff --git a/src/Test/Unit/Docker/ConfigTest.php b/src/Test/Unit/Docker/ConfigTest.php new file mode 100644 index 0000000000..0cb019ab17 --- /dev/null +++ b/src/Test/Unit/Docker/ConfigTest.php @@ -0,0 +1,118 @@ +readerMock = $this->createMock(Config\Reader::class); + + $this->config = new Config( + $this->readerMock + ); + } + + /** + * @throws ConfigurationMismatchException + */ + public function testGetServiceVersion() + { + $this->readerMock->expects($this->once()) + ->method('read') + ->willReturn([ + 'services' => [ + Config::KEY_DB => [ + 'version' => '10.0' + ] + ] + ]); + + $this->assertSame('10.0', $this->config->getServiceVersion(Config::KEY_DB)); + } + + /** + * @expectedExceptionMessage Some error + * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException + * + * @throws ConfigurationMismatchException + */ + public function testGetServiceVersionWithException() + { + $this->readerMock->expects($this->once()) + ->method('read') + ->willThrowException(new FileSystemException('Some error')); + + $this->assertSame('10.0', $this->config->getServiceVersion(Config::KEY_DB)); + } + + /** + * @throws ConfigurationMismatchException + */ + public function testGetPhpVersion() + { + $this->readerMock->expects($this->once()) + ->method('read') + ->willReturn([ + 'type' => 'php:7.0-rc' + ]); + + $this->assertSame('7.0', $this->config->getPhpVersion()); + } + + /** + * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException + * @expectedExceptionMessage Type "ruby" is not supported + * + * @throws ConfigurationMismatchException + */ + public function testGetPhpVersionBroken() + { + $this->readerMock->expects($this->once()) + ->method('read') + ->willReturn([ + 'type' => 'ruby:2.0' + ]); + + $this->config->getPhpVersion(); + } + + /** + * @expectedExceptionMessage Some error + * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException + * + * @throws ConfigurationMismatchException + */ + public function testGetPhpVersionWithReadException() + { + $this->readerMock->expects($this->once()) + ->method('read') + ->willThrowException(new FileSystemException('Some error')); + + $this->config->getPhpVersion(); + } +} diff --git a/src/Test/Unit/Docker/DevBuilderTest.php b/src/Test/Unit/Docker/DevBuilderTest.php index e3fe034894..2eee9d79f0 100644 --- a/src/Test/Unit/Docker/DevBuilderTest.php +++ b/src/Test/Unit/Docker/DevBuilderTest.php @@ -3,15 +3,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Test\Unit\Docker; -use Illuminate\Contracts\Config\Repository; -use Magento\MagentoCloud\Config\RepositoryFactory; +use Illuminate\Config\Repository; use Magento\MagentoCloud\Docker\BuilderInterface; +use Magento\MagentoCloud\Docker\Config; use Magento\MagentoCloud\Docker\ConfigurationMismatchException; use Magento\MagentoCloud\Docker\DevBuilder; use Magento\MagentoCloud\Docker\Service\ServiceFactory; -use Magento\MagentoCloud\Docker\Service\ServiceInterface; +use Magento\MagentoCloud\Filesystem\FileList; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -26,17 +28,17 @@ class DevBuilderTest extends TestCase private $builder; /** - * @var RepositoryFactory|MockObject + * @var ServiceFactory|MockObject */ - private $repositoryFactoryMock; + private $serviceFactoryMock; /** - * @var ServiceFactory|MockObject + * @var FileList|MockObject */ - private $serviceFactoryMock; + private $fileListMock; /** - * @var Repository|MockObject + * @var Config|MockObject */ private $configMock; @@ -45,168 +47,62 @@ class DevBuilderTest extends TestCase */ protected function setUp() { - $this->repositoryFactoryMock = $this->createMock(RepositoryFactory::class); - $this->configMock = $this->getMockForAbstractClass(Repository::class); - $this->serviceFactoryMock = $this->createMock(ServiceFactory::class); - - $this->repositoryFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->configMock); + $this->serviceFactoryMock = $this->createTestProxy(ServiceFactory::class); + $this->fileListMock = $this->createMock(FileList::class); + $this->configMock = $this->createMock(Config::class); $this->builder = new DevBuilder( - $this->repositoryFactoryMock, - $this->serviceFactoryMock + $this->serviceFactoryMock, + $this->fileListMock, + $this->configMock ); } - /** - * @param string $version - * @dataProvider setNginxVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetNginxVersion(string $version) - { - $this->configMock->expects($this->once()) - ->method('set') - ->with('nginx.version', $version); - - $this->builder->setNginxVersion($version); - } - - /** - * @return array - */ - public function setNginxVersionDataProvider(): array - { - return [ - ['1.9'], - [DevBuilder::DEFAULT_NGINX_VERSION,], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service nginx:2 is not supported - */ - public function testSetNginxWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setNginxVersion('2'); - } - - /** - * @param string $version - * @dataProvider setPhpVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetPhpVersion(string $version) - { - $this->configMock->expects($this->once()) - ->method('set') - ->with('php.version', $version); - - $this->builder->setPhpVersion($version); - } - - /** - * @return array - */ - public function setPhpVersionDataProvider(): array - { - return [ - ['7.0'], - [DevBuilder::DEFAULT_PHP_VERSION,], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service php:2 is not supported - */ - public function testSetPhpWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setPhpVersion('2'); - } - - /** - * @param string $version - * @dataProvider setDbVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetDbVersion(string $version) + public function testGetConfigPath() { - $this->configMock->expects($this->once()) - ->method('set') - ->with('db.version', $version); - - $this->builder->setDbVersion($version); - } + $this->fileListMock->expects($this->once()) + ->method('getMagentoDockerCompose') + ->willReturn('/ece/docker-compose.yaml'); - /** - * @return array - */ - public function setDbVersionDataProvider(): array - { - return [ - [DevBuilder::DEFAULT_DB_VERSION], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service db:2 is not supported - */ - public function testSetDbWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setDbVersion('2'); + $this->assertSame('/ece/docker-compose.yaml', $this->builder->getConfigPath()); } /** * @throws ConfigurationMismatchException */ - public function testSetRabbitMQVersion() + public function testBuild() { - $this->configMock->expects($this->once()) - ->method('set') - ->with(BuilderInterface::RABBIT_MQ_VERSION, '3.5'); + $config = new Repository([ + BuilderInterface::NGINX_VERSION => 'latest', + BuilderInterface::PHP_VERSION => '7.0', + BuilderInterface::DB_VERSION => '10.0' + ]); - $this->builder->setRabbitMQVersion('3.5'); + $this->builder->build($config); } /** * @throws ConfigurationMismatchException */ - public function testSetESVersion() + public function testBuildFromConfig() { - $this->configMock->expects($this->once()) - ->method('set') - ->with(BuilderInterface::ES_VERSION, '2.4'); - - $this->builder->setESVersion('2.4'); - } - - public function testBuild() - { - $serviceMock = $this->getMockForAbstractClass(ServiceInterface::class); - $serviceMock->expects($this->any()) - ->method('get') - ->willReturn([]); - - $this->serviceFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($serviceMock); - - $config = $this->builder->build(); - - $this->assertArrayHasKey('version', $config); - $this->assertArrayHasKey('services', $config); + $config = new Repository(); + + $this->configMock->method('getServiceVersion') + ->willReturnMap([ + [Config::KEY_DB, '10.0'], + ]); + $this->configMock->method('getPhpVersion') + ->willReturn('7.0'); + + $build = $this->builder->build($config); + + $this->assertArrayNotHasKey('redis', $build['services']); + $this->assertArrayNotHasKey('rabbitmq', $build['services']); + $this->assertArrayNotHasKey('elasticsearch', $build['services']); + $this->assertArrayHasKey('cli', $build['services']); + $this->assertArrayHasKey('build', $build['services']); + $this->assertArrayHasKey('deploy', $build['services']); + $this->assertArrayHasKey('db', $build['services']); } } diff --git a/src/Test/Unit/Docker/IntegrationBuilderTest.php b/src/Test/Unit/Docker/IntegrationBuilderTest.php index 2a8dfd657a..331d8d2579 100644 --- a/src/Test/Unit/Docker/IntegrationBuilderTest.php +++ b/src/Test/Unit/Docker/IntegrationBuilderTest.php @@ -3,14 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Test\Unit\Docker; -use Illuminate\Contracts\Config\Repository; -use Magento\MagentoCloud\Config\RepositoryFactory; +use Illuminate\Config\Repository; use Magento\MagentoCloud\Docker\BuilderInterface; use Magento\MagentoCloud\Docker\ConfigurationMismatchException; -use Magento\MagentoCloud\Docker\Service\ServiceInterface; +use Magento\MagentoCloud\Docker\Service\ServiceFactory; use Magento\MagentoCloud\Docker\IntegrationBuilder; +use Magento\MagentoCloud\Filesystem\FileList; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -25,175 +27,52 @@ class IntegrationBuilderTest extends TestCase private $builder; /** - * @var RepositoryFactory|MockObject + * @var FileList|MockObject */ - private $repositoryFactoryMock; + private $fileListMock; /** - * @var Repository|MockObject + * @var ServiceFactory|MockObject */ - private $configMock; + private $serviceFactoryMock; /** * @inheritdoc */ protected function setUp() { - $this->repositoryFactoryMock = $this->createMock(RepositoryFactory::class); - $this->configMock = $this->getMockForAbstractClass(Repository::class); - - $this->repositoryFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->configMock); + $this->fileListMock = $this->createMock(FileList::class); + $this->serviceFactoryMock = $this->createTestProxy(ServiceFactory::class); $this->builder = new IntegrationBuilder( - $this->repositoryFactoryMock + $this->fileListMock, + $this->serviceFactoryMock ); } - /** - * @param string $version - * @dataProvider setNginxVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetNginxVersion(string $version) - { - $this->configMock->expects($this->once()) - ->method('set') - ->with('nginx.version', $version); - - $this->builder->setNginxVersion($version); - } - - /** - * @return array - */ - public function setNginxVersionDataProvider(): array - { - return [ - ['1.9'], - [IntegrationBuilder::DEFAULT_NGINX_VERSION,], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service nginx:2 is not supported - */ - public function testSetNginxWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setNginxVersion('2'); - } - - /** - * @param string $version - * @dataProvider setPhpVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetPhpVersion(string $version) - { - $this->configMock->expects($this->once()) - ->method('set') - ->with('php.version', $version); - - $this->builder->setPhpVersion($version); - } - - /** - * @return array - */ - public function setPhpVersionDataProvider(): array - { - return [ - ['7.0'], - [IntegrationBuilder::DEFAULT_PHP_VERSION,], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service php:2 is not supported - */ - public function testSetPhpWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setPhpVersion('2'); - } - - /** - * @param string $version - * @dataProvider setDbVersionDataProvider - * @throws \Magento\MagentoCloud\Docker\ConfigurationMismatchException - */ - public function testSetDbVersion(string $version) - { - $this->configMock->expects($this->once()) - ->method('set') - ->with('db.version', $version); - - $this->builder->setDbVersion($version); - } - - /** - * @return array - */ - public function setDbVersionDataProvider(): array - { - return [ - [IntegrationBuilder::DEFAULT_DB_VERSION], - ]; - } - - /** - * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException - * @expectedExceptionMessage Service db:2 is not supported - */ - public function testSetDbWithError() - { - $this->configMock->expects($this->never()) - ->method('set'); - - $this->builder->setDbVersion('2'); - } - - /** - * @throws ConfigurationMismatchException - */ - public function testSetRabbitMQVersion() - { - $this->configMock->expects($this->once()) - ->method('set') - ->with(BuilderInterface::RABBIT_MQ_VERSION, '3.5'); - - $this->builder->setRabbitMQVersion('3.5'); - } - /** * @throws ConfigurationMismatchException */ - public function testSetESVersion() + public function testBuild() { - $this->configMock->expects($this->once()) - ->method('set') - ->with(BuilderInterface::ES_VERSION, '2.4'); + $config = new Repository([ + BuilderInterface::DB_VERSION => '10.0', + BuilderInterface::PHP_VERSION => '7.0', + BuilderInterface::NGINX_VERSION => 'latest' + ]); - $this->builder->setESVersion('2.4'); + $this->builder->build($config); } - public function testBuild() + public function testGetConfigPath() { - $serviceMock = $this->getMockForAbstractClass(ServiceInterface::class); - $serviceMock->method('get') - ->willReturn([]); + $this->fileListMock->expects($this->once()) + ->method('getToolsDockerCompose') + ->willReturn('/tools/docker-compose.yaml'); - $config = $this->builder->build(); - - $this->assertArrayHasKey('version', $config); - $this->assertArrayHasKey('services', $config); + $this->assertSame( + '/tools/docker-compose.yaml', + $this->builder->getConfigPath() + ); } } diff --git a/src/Test/Unit/Docker/Service/ServiceFactoryTest.php b/src/Test/Unit/Docker/Service/ServiceFactoryTest.php index 9f3122ca84..8334c63a70 100644 --- a/src/Test/Unit/Docker/Service/ServiceFactoryTest.php +++ b/src/Test/Unit/Docker/Service/ServiceFactoryTest.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\MagentoCloud\Test\Unit\Docker\Service; -use Magento\MagentoCloud\App\ContainerInterface; +use Magento\MagentoCloud\Docker\ConfigurationMismatchException; use Magento\MagentoCloud\Docker\Service\ServiceFactory; -use Magento\MagentoCloud\Docker\Service\VarnishService; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; /** @@ -21,30 +21,41 @@ class ServiceFactoryTest extends TestCase */ private $factory; - /** - * @var ContainerInterface|MockObject - */ - private $containerMock; - /** * @inheritdoc */ protected function setUp() { - $this->containerMock = $this->getMockForAbstractClass(ContainerInterface::class); - - $this->factory = new ServiceFactory( - $this->containerMock - ); + $this->factory = new ServiceFactory(); } + /** + * @throws ConfigurationMismatchException + */ public function testCreate() { - $this->containerMock->expects($this->once()) - ->method('create') - ->with(VarnishService::class) - ->willReturn($this->createMock(VarnishService::class)); + $this->factory->create(ServiceFactory::SERVICE_CLI, '7.0'); + } + + /** + * @expectedExceptionMessage Service "php-cli" does not support version "5.6" + * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException + * + * @throws ConfigurationMismatchException + */ + public function testCreateVersionNotSupported() + { + $this->factory->create(ServiceFactory::SERVICE_CLI, '5.6'); + } - $this->factory->create(ServiceFactory::SERVICE_VARNISH); + /** + * @expectedExceptionMessage Service "test" is not supported + * @expectedException \Magento\MagentoCloud\Docker\ConfigurationMismatchException + * + * @throws ConfigurationMismatchException + */ + public function testCreateServiceNotSupported() + { + $this->factory->create('test', '5.6'); } } diff --git a/src/Test/Unit/Docker/Service/VarnishServiceTest.php b/src/Test/Unit/Docker/Service/VarnishServiceTest.php deleted file mode 100644 index 8074adafa6..0000000000 --- a/src/Test/Unit/Docker/Service/VarnishServiceTest.php +++ /dev/null @@ -1,46 +0,0 @@ -service = new VarnishService(); - } - - public function testGet() - { - $this->assertSame([ - 'image' => 'magento/magento-cloud-docker-varnish:latest', - 'environment' => [ - 'VIRTUAL_HOST' => 'magento2.docker', - 'VIRTUAL_PORT' => 80, - 'HTTPS_METHOD' => 'noredirect', - ], - 'ports' => [ - '80:80', - ], - 'depends_on' => [ - 'web', - ], - ], $this->service->get()); - } -} diff --git a/tests/unit/code-coverage.php b/tests/unit/code-coverage.php index 3e20256664..e2fbf73fcd 100644 --- a/tests/unit/code-coverage.php +++ b/tests/unit/code-coverage.php @@ -3,7 +3,7 @@ * @author Marco Pivetta * @link https://ocramius.github.io/blog/automated-code-coverage-check-for-github-pull-requests-with-travis/ */ -const MIN_COVERAGE = 92; +const MIN_COVERAGE = 93; $inputFile = $argv[1]; $percentage = min(100, max(0, MIN_COVERAGE));