diff options
-rw-r--r-- | composer.json | 2 | ||||
-rw-r--r-- | composer.lock | 263 | ||||
-rwxr-xr-x | config/global.ini.php | 12 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/CloudWatch.php | 128 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/Config.php | 99 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/Instance.php | 191 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/Ssh.php | 55 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/Tags.php | 43 | ||||
-rw-r--r-- | plugins/TestRunner/Aws/config.ini.php | 26 | ||||
-rw-r--r-- | plugins/TestRunner/Commands/TestsRunOnAws.php | 179 | ||||
-rw-r--r-- | plugins/TestRunner/README.md | 69 | ||||
-rw-r--r-- | plugins/TestRunner/Runner/InstanceLauncher.php | 53 | ||||
-rw-r--r-- | plugins/TestRunner/Runner/Remote.php | 99 | ||||
-rw-r--r-- | plugins/TestRunner/screenshots/.gitkeep | 0 | ||||
-rw-r--r-- | plugins/TestRunner/scripts/on_instance_launch.sh | 9 |
15 files changed, 1 insertions, 1227 deletions
diff --git a/composer.json b/composer.json index 4239c01df2..b66bec9c80 100644 --- a/composer.json +++ b/composer.json @@ -54,9 +54,7 @@ "twig/twig": "~1.0" }, "require-dev": { - "aws/aws-sdk-php": "2.7.1", "lox/xhprof": "dev-master", - "phpseclib/phpseclib": "~0.3.8", "phpunit/phpunit": "~8.5", "symfony/var-dumper": "~2.6.0", "symfony/yaml": "~2.6.0" diff --git a/composer.lock b/composer.lock index 0d7af66819..54a634afc9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "71f3276bfe58917f2a7b5bdd2d993f9a", + "content-hash": "a03445c07f2354bce4f64a147a55cdb3", "packages": [ { "name": "composer/ca-bundle", @@ -1890,73 +1890,6 @@ ], "packages-dev": [ { - "name": "aws/aws-sdk-php", - "version": "2.7.1", - "source": { - "type": "git", - "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "937a39ca3cee98d31a7410a17db24e0496c41494" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/937a39ca3cee98d31a7410a17db24e0496c41494", - "reference": "937a39ca3cee98d31a7410a17db24e0496c41494", - "shasum": "" - }, - "require": { - "guzzle/guzzle": "~3.7", - "php": ">=5.3.3" - }, - "require-dev": { - "doctrine/cache": "~1.0", - "ext-openssl": "*", - "monolog/monolog": "~1.4", - "phpunit/phpunit": "~4.0", - "symfony/yaml": "~2.1" - }, - "suggest": { - "doctrine/cache": "Adds support for caching of credentials and responses", - "ext-apc": "Allows service description opcode caching, request and response caching, and credentials caching", - "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", - "monolog/monolog": "Adds support for logging HTTP requests and responses", - "symfony/yaml": "Eases the ability to write manifests for creating jobs in AWS Import/Export" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-0": { - "Aws": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Amazon Web Services", - "homepage": "http://aws.amazon.com" - } - ], - "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", - "homepage": "http://aws.amazon.com/sdkforphp", - "keywords": [ - "amazon", - "aws", - "cloud", - "dynamodb", - "ec2", - "glacier", - "s3", - "sdk" - ], - "time": "2014-10-16T21:37:55+00:00" - }, - { "name": "doctrine/instantiator", "version": "1.3.0", "source": { @@ -2013,102 +1946,6 @@ "time": "2019-10-21T16:45:58+00:00" }, { - "name": "guzzle/guzzle", - "version": "v3.9.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, - "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", - "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" - }, - "suggest": { - "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.9-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "abandoned": "guzzlehttp/guzzle", - "time": "2015-03-18T18:23:50+00:00" - }, - { "name": "lox/xhprof", "version": "dev-master", "source": { @@ -2450,104 +2287,6 @@ "time": "2019-08-22T18:11:29+00:00" }, { - "name": "phpseclib/phpseclib", - "version": "0.3.10", - "source": { - "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "d15bba1edcc7c89e09cc74c5d961317a8b947bf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d15bba1edcc7c89e09cc74c5d961317a8b947bf4", - "reference": "d15bba1edcc7c89e09cc74c5d961317a8b947bf4", - "shasum": "" - }, - "require": { - "php": ">=5.0.0" - }, - "require-dev": { - "phing/phing": "~2.7", - "phpunit/phpunit": "~4.0", - "sami/sami": "~2.0", - "squizlabs/php_codesniffer": "~1.5" - }, - "suggest": { - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.", - "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 4.3.3." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.3-dev" - } - }, - "autoload": { - "psr-0": { - "Crypt": "phpseclib/", - "File": "phpseclib/", - "Math": "phpseclib/", - "Net": "phpseclib/", - "System": "phpseclib/" - }, - "files": [ - "phpseclib/Crypt/Random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "phpseclib/" - ], - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" - }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" - }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" - }, - { - "name": "Hans-Jürgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" - } - ], - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "homepage": "http://phpseclib.sourceforge.net", - "keywords": [ - "BigInteger", - "aes", - "asn.1", - "asn1", - "blowfish", - "crypto", - "cryptography", - "encryption", - "rsa", - "security", - "sftp", - "signature", - "signing", - "ssh", - "twofish", - "x.509", - "x509" - ], - "time": "2015-01-28T21:50:33+00:00" - }, - { "name": "phpspec/prophecy", "version": "v1.10.2", "source": { diff --git a/config/global.ini.php b/config/global.ini.php index 0097c19187..6579231b8c 100755 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -86,18 +86,6 @@ request_uri = "@REQUEST_URI@" port = enable_logging = 0 -; access key and secret as listed in AWS -> IAM -> Users -aws_accesskey = "" -aws_secret = "" -; key pair name as listed in AWS -> EC2 -> Key Pairs. Key name should be different per user. -aws_keyname = "" -; PEM file can be downloaded after creating a new key pair in AWS -> EC2 -> Key Pairs -aws_pem_file = "<path to pem file>" -aws_securitygroups[] = "default" -aws_region = "us-east-1" -aws_ami = "ami-ac24bac4" -aws_instance_type = "c3.large" - [log] ; possible values for log: screen, database, file log_writers[] = screen diff --git a/plugins/TestRunner/Aws/CloudWatch.php b/plugins/TestRunner/Aws/CloudWatch.php deleted file mode 100644 index 334d80442e..0000000000 --- a/plugins/TestRunner/Aws/CloudWatch.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Aws; - -use Aws\CloudWatch\CloudWatchClient; -use Aws\CloudWatch\Enum\ComparisonOperator; -use Aws\CloudWatch\Enum\Statistic; -use Aws\CloudWatch\Enum\Unit; - -class CloudWatch -{ - /** - * @var Config - */ - private $config; - - /** - * @var CloudWatchClient - */ - private $client; - - public function __construct(Config $awsConfig) - { - $this->config = $awsConfig; - $this->client = $this->getCloudWatchClient(); - } - - public function hasAssignedAlarms($instanceIds) - { - $result = $this->client->describeAlarmsForMetric(array( - 'MetricName' => 'CPUUtilization', - 'Namespace' => $this->getNamespace(), - 'Dimensions' => $this->getDimensions($instanceIds) - )); - - $metricAlarms = $result->getPath('MetricAlarms'); - - return !empty($metricAlarms); - } - - public function terminateInstanceIfIdleForTooLong($instanceIds) - { - $this->client->putMetricAlarm(array( - 'AlarmName' => 'TerminateInstanceBecauseIdle', - 'AlarmDescription' => 'Terminate instances if CPU is on average < 10% for 5 minutes in a row 8 times consecutively', - 'ActionsEnabled' => true, - 'OKActions' => array(), - 'AlarmActions' => $this->getAlarmActions(), - 'InsufficientDataActions' => array(), - 'MetricName' => 'CPUUtilization', - 'Namespace' => $this->getNamespace(), - 'Statistic' => Statistic::AVERAGE, - 'Dimensions' => $this->getDimensions($instanceIds), - 'Period' => 300, - 'Unit' => Unit::PERCENT, - 'EvaluationPeriods' => 8, - 'Threshold' => 10, - 'ComparisonOperator' => ComparisonOperator::LESS_THAN_THRESHOLD, - )); - - $this->client->putMetricAlarm(array( - 'AlarmName' => 'TerminateInstanceIfStatusCheckFails', - 'AlarmDescription' => 'Terminate instances in case two status check fail within one minute', - 'ActionsEnabled' => true, - 'OKActions' => array(), - 'AlarmActions' => $this->getAlarmActions(), - 'InsufficientDataActions' => array(), - 'MetricName' => 'StatusCheckFailed', - 'Namespace' => $this->getNamespace(), - 'Statistic' => Statistic::AVERAGE, - 'Dimensions' => $this->getDimensions($instanceIds), - 'Period' => 60, - 'Unit' => Unit::PERCENT, - 'EvaluationPeriods' => 2, - 'Threshold' => 1, - 'ComparisonOperator' => ComparisonOperator::GREATER_THAN_OR_EQUAL_TO_THRESHOLD, - )); - } - - private function getCloudWatchClient() - { - return CloudWatchClient::factory($this->getConnectionOptions()); - } - - private function getConnectionOptions() - { - return array( - 'key' => $this->config->getAccessKey(), - 'secret' => $this->config->getSecretKey(), - 'region' => $this->config->getRegion() - ); - } - - private function getDimensions($instanceIds) - { - $dimensions = array(); - - foreach ($instanceIds as $instanceId) { - $dimensions[] = array( - 'Name' => 'InstanceId', - 'Value' => $instanceId, - ); - } - - return $dimensions; - } - - private function getNamespace() - { - return 'AWS/EC2'; - } - - private function getAlarmActions() - { - return array( - 'arn:aws:automate:' . $this->config->getRegion() . ':ec2:terminate', - 'arn:aws:sns:' . $this->config->getRegion() . ':682510200394:TerminateInstanceBecauseIdle' - ); - } - -} diff --git a/plugins/TestRunner/Aws/Config.php b/plugins/TestRunner/Aws/Config.php deleted file mode 100644 index d01b1f3d01..0000000000 --- a/plugins/TestRunner/Aws/Config.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Aws; - -use \Piwik\Config as PiwikConfig; - -class Config -{ - public function getRegion() - { - return trim($this->getConfigValue('aws_region')); - } - - public function getAmi() - { - return trim($this->getConfigValue('aws_ami')); - } - - public function getInstanceType() - { - return trim($this->getConfigValue('aws_instance_type')); - } - - public function getKeyName() - { - return $this->getConfigValue('aws_keyname'); - } - - public function getPemFile() - { - return trim($this->getConfigValue('aws_pem_file')); - } - - public function getAccessKey() - { - return trim($this->getConfigValue('aws_accesskey')); - } - - public function getSecretKey() - { - return trim($this->getConfigValue('aws_secret')); - } - - public function getSecurityGroups() - { - $groups = $this->getConfigValue('aws_securitygroups'); - - if (empty($groups)) { - $groups = array(); - } - - return (array) $groups; - } - - public function validate() - { - $configKeysToValidate = array( - 'aws_accesskey', - 'aws_secret', - 'aws_region', - 'aws_ami', - 'aws_instance_type', - 'aws_pem_file', - 'aws_keyname', - 'aws_securitygroups', - ); - - foreach ($configKeysToValidate as $key) { - if (!$this->getConfigValue($key)) { - throw new \RuntimeException("[tests]$key is not configured in config/config.ini.php"); - } - } - - $pemFile = $this->getPemFile(); - - if (!file_exists($pemFile)) { - throw new \RuntimeException('[tests]aws_pem_file the file does not exist or is not readable'); - } - } - - private function getConfig() - { - return PiwikConfig::getInstance()->tests; - } - - private function getConfigValue($key) - { - $config = $this->getConfig(); - - return $config[$key]; - } -} diff --git a/plugins/TestRunner/Aws/Instance.php b/plugins/TestRunner/Aws/Instance.php deleted file mode 100644 index db706e36e0..0000000000 --- a/plugins/TestRunner/Aws/Instance.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Aws; - -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Aws\Ec2\Ec2Client; - -class Instance -{ - - /** - * @var Config - */ - private $config; - - /** - * @var Ec2Client - */ - private $client; - - private $testSuite; - - private $useOneInstancePerTestSuite = false; - - public function __construct(Config $config, $testSuite) - { - $this->config = $config; - $this->testSuite = $testSuite; - $this->client = $this->createEc2Client(); - } - - public function enableUseOneInstancePerTestSuite() - { - $this->useOneInstancePerTestSuite = true; - } - - public function findExisting() - { - $filters = array( - array('Name' => 'image-id', 'Values' => array($this->config->getAmi())), - array('Name' => 'key-name', 'Values' => array($this->config->getKeyName())), - array('Name' => 'instance-state-name', 'Values' => array('running')), - ); - - if (!empty($this->testSuite) && $this->useOneInstancePerTestSuite) { - $filters[] = array('Name' => 'tag:TestSuite', 'Values' => array($this->testSuite)); - } - - $instances = $this->client->describeInstances(array('Filters' => $filters)); - - $reservations = $instances->getPath('Reservations'); - - if (!empty($reservations)) { - $host = $this->getHostFromDescribedInstances($instances); - - $instanceIds = $instances->getPath('Reservations/*/Instances/*/InstanceId'); - $this->verifySetup($instanceIds); - - return $host; - } - } - - public function terminate($instanceIds) - { - $this->client->terminateInstances(array( - 'InstanceIds' => $instanceIds - )); - - $this->client->waitUntilInstanceTerminated(array( - 'InstanceIds' => $instanceIds - )); - } - - public function launch() - { - // user data is executed when instance launches, it is important that this file starts with "#!" - $userData = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/TestRunner/scripts/on_instance_launch.sh'); - - $result = $this->client->runInstances(array( - 'ImageId' => $this->config->getAmi(), - 'MinCount' => 1, - 'MaxCount' => 1, - 'InstanceType' => $this->config->getInstanceType(), - 'KeyName' => $this->config->getKeyName(), - 'SecurityGroups' => $this->config->getSecurityGroups(), - 'InstanceInitiatedShutdownBehavior' => 'terminate', - 'UserData' => base64_encode($userData) - )); - - $instanceIds = $result->getPath('Instances/*/InstanceId'); - - $this->client->waitUntilInstanceRunning(array( - 'InstanceIds' => $instanceIds, - )); - - return $instanceIds; - } - - public function setup($instanceIds) - { - $awsCloudWatch = new CloudWatch($this->config); - $awsCloudWatch->terminateInstanceIfIdleForTooLong($instanceIds); - - $awsTags = new Tags($this->client); - $awsTags->assignTagsToInstances($instanceIds, $this->testSuite); - - $instances = $this->client->describeInstances(array( - 'InstanceIds' => $instanceIds, - )); - - $host = $this->getHostFromDescribedInstances($instances); - - return $host; - } - - public function verifySetup($instanceIds) - { - $awsCloudWatch = new CloudWatch($this->config); - $hasAlarms = $awsCloudWatch->hasAssignedAlarms($instanceIds); - - if (!$hasAlarms) { - $this->setup($instanceIds); // try setup again - - $hasAlarms = $awsCloudWatch->hasAssignedAlarms($instanceIds); - - if (!$hasAlarms) { // declare it as failed if it still does not work - throw new \Exception('Failed to assign alarms for InstanceIds: ' . implode(', ' , $instanceIds)); - } - } - } - - /** - * @param \Guzzle\Service\Resource\Model $resources - * @return mixed - */ - private function getHostFromDescribedInstances($resources) - { - $instances = $resources->getPath('Reservations/*/Instances'); - - if (empty($instances)) { - return; - } - - $instanceToUse = null; - - foreach ($instances as $index => $instance) { - if (!empty($instance['Tags'])) { - foreach ($instance['Tags'] as $tag) { - if (!empty($this->testSuite) - && $tag['Key'] === 'TestSuite' - && $tag['Value'] === $this->testSuite) { - - $instanceToUse = $instance; - } - } - } - } - - if (empty($instanceToUse)) { - $instanceToUse = array_shift($instances); - } - - $host = $instanceToUse['PublicDnsName']; - - return $host; - } - - private function createEc2Client() - { - return Ec2Client::factory($this->getConnectionOptions()); - } - - private function getConnectionOptions() - { - return array( - 'key' => $this->config->getAccessKey(), - 'secret' => $this->config->getSecretKey(), - 'region' => $this->config->getRegion() - ); - } -}
\ No newline at end of file diff --git a/plugins/TestRunner/Aws/Ssh.php b/plugins/TestRunner/Aws/Ssh.php deleted file mode 100644 index 2ca2e228ad..0000000000 --- a/plugins/TestRunner/Aws/Ssh.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Aws; -use Symfony\Component\Console\Output\OutputInterface; -use Crypt_RSA; -use Net_SSH2; - -class Ssh extends Net_SSH2 -{ - /** - * @var OutputInterface - */ - private $output; - - public static function connectToAws($host, $pemFile) - { - $key = new Crypt_RSA(); - $key->loadKey(file_get_contents($pemFile)); - - $ssh = new Ssh($host); - - if (!$ssh->login('ubuntu', $key)) { - $error = error_get_last(); - throw new \RuntimeException("Login to $host using $pemFile failed: " . $error['message']); - } - - return $ssh; - } - - public function setOutput(OutputInterface $output) - { - $this->output = $output; - } - - public function exec($command, $callback = null) - { - $command = 'cd www/piwik && ' . $command; - $output = $this->output; - - $output->writeln("Executing <comment>$command</comment>"); - - return parent::exec($command, function($tempOutput) use ($output) { - if ($output) { - $output->write($tempOutput); - } - }); - } -} diff --git a/plugins/TestRunner/Aws/Tags.php b/plugins/TestRunner/Aws/Tags.php deleted file mode 100644 index cbf81d3d8c..0000000000 --- a/plugins/TestRunner/Aws/Tags.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Aws; -use Aws\Ec2\Ec2Client; - -class Tags -{ - /** - * @var Ec2Client - */ - private $ec2Client; - - public function __construct(Ec2Client $client) - { - $this->ec2Client = $client; - } - - public function assignTagsToInstances($instanceIds, $testSuite) - { - $tags = array($this->buildTag('Name', 'PiwikTesting')); - - if (!empty($testSuite)) { - $tags[] = $this->buildTag('TestSuite', $testSuite); - } - - $this->ec2Client->createTags(array('Resources' => $instanceIds, 'Tags' => $tags)); - } - - private function buildTag($name, $value) - { - return array( - 'Key' => $name, - 'Value' => $value, - ); - } -}
\ No newline at end of file diff --git a/plugins/TestRunner/Aws/config.ini.php b/plugins/TestRunner/Aws/config.ini.php deleted file mode 100644 index c83e0aafd1..0000000000 --- a/plugins/TestRunner/Aws/config.ini.php +++ /dev/null @@ -1,26 +0,0 @@ -; <?php exit; ?> DO NOT REMOVE THIS LINE -; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file. -[database] -host = "127.0.0.1" -username = "root" -password = "secure" -dbname = "piwik" -tables_prefix = "piwik_" -charset = "utf8" - -[tests] -request_uri = "/" - -[database_tests] -username = "root" -password = "secure" -tables_prefix = "" - -[General] -salt = "ad40b992685bd402cdddaa46bdff537e" -enable_update_communication = 0 -trusted_hosts[] = "amazonaws.com" -trusted_hosts[] = "www.example.com" -trusted_hosts[] = "apache.piwik" -trusted_hosts[] = "nginx.piwik" -trusted_hosts[] = "amazonAwsUrl" diff --git a/plugins/TestRunner/Commands/TestsRunOnAws.php b/plugins/TestRunner/Commands/TestsRunOnAws.php deleted file mode 100644 index 4150145f44..0000000000 --- a/plugins/TestRunner/Commands/TestsRunOnAws.php +++ /dev/null @@ -1,179 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Commands; - -use Piwik\Development; -use Piwik\Plugin\ConsoleCommand; -use Piwik\Plugins\TestRunner\Aws\Config; -use Piwik\Plugins\TestRunner\Aws\Instance; -use Piwik\Plugins\TestRunner\Aws\Ssh; -use Piwik\Plugins\TestRunner\Runner\InstanceLauncher; -use Piwik\Plugins\TestRunner\Runner\Remote; -use Piwik\SettingsPiwik; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class TestsRunOnAws extends ConsoleCommand -{ - private $allowedTestSuites = array('integration', 'system', 'all', 'ui'); - - public function isEnabled() - { - return Development::isEnabled(); - } - - protected function configure() - { - $this->setName('tests:run-aws'); - $this->addArgument('testsuite', InputArgument::OPTIONAL, 'Allowed values: ' . implode(', ', $this->allowedTestSuites)); - $this->addArgument('arguments', InputArgument::IS_ARRAY, 'Any additional argument will be passed to the test command.'); - $this->addOption('launch-only', null, InputOption::VALUE_NONE, 'Only launches an instance and outputs the connection parameters. Useful if you want to connect via SSH.'); - $this->addOption('update-only', null, InputOption::VALUE_NONE, 'Launches an instance, outputs the connection parameters and prepares the instance for a test run but does not actually run the tests. It will also checkout the specified version.'); - $this->addOption('one-instance-per-testsuite', null, InputOption::VALUE_NONE, 'Launches one instance for system tests and one for ui tests.'); - $this->addOption('checkout', null, InputOption::VALUE_REQUIRED, 'Git hash, tag or branch to checkout. Defaults to current hash', $this->getCurrentGitHash()); - $this->addOption('patch-file', null, InputOption::VALUE_REQUIRED, 'Apply the given patch file after performing a checkout'); - $this->setDescription('Run a specific testsuite on AWS'); - $this->setHelp('To use this command you have to configure the [tests]aws_* section in config/config.ini.php. See config/global.ini.php for all available options. - -To run a test simply specify the testsuite you want to run: <comment>./console tests:run-aws system</comment>. This will launch a new instance on AWS or reuse an already running one. We start one instance per keyname. This makes sure two different developers do not use the same instance at the same time. - -By default it will execute the tests of the git hash you are currently on. If this hash is not pushed yet or if you want to run tests of a specific git hash / branch / tag use the <comment>--checkout</comment> option: <comment>./console tests:run-aws --checkout="master" system</comment>. - -If you want to debug a problem and access the AWS instance using SSH you can specify the <comment>--launch-only</comment> or <comment>--update-only</comment> option. - -By default we will launch only one instance per keyname meaning you should not execute this command while another test is running. It would start the tests twice on the same instance and lead to errors. If you want to run two different testsuites at the same time (for instance <comment>system</comment> and <comment>ui</comment>) specify the <comment>one-instance-per-testsuite</comment> option. This will launch one instance for system tests and one for ui tests: -<comment>./console tests:run-aws system</comment> -<comment>./console tests:run-aws --one-instance-per-testsuite ui // will launch a new instance for ui testsuites</comment> - -If you want to apply a patch on top of the checked out version you can apply the option <comment>--patch-file</comment>. -<comment>./console tests:run-aws --patch-file=test.patch ui</comment> -This will checkout the same revision as you are currently on and then apply the patch. To generate a diff use for instance the command <comment>git diff > test.patch</comment>. -This feature is still beta and there might be problems with pictures and/or binaries etc. - -You can also pass any argument to the command and they will be forwarded to the test command, for example to run a specific UI test: <comment>./console tests:run-aws ui Dashboard</comment>. -'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $testSuite = $this->getTestSuite($input); - $arguments = $input->getArgument('arguments'); - $patchFile = $this->getPatchFile($input); - $launchOnly = $input->getOption('launch-only'); - $updateOnly = $input->getOption('update-only'); - $gitHash = $input->getOption('checkout'); - $perTestsuite = $input->getOption('one-instance-per-testsuite'); - - if (empty($testSuite) && empty($launchOnly) && empty($updateOnly)) { - throw new \InvalidArgumentException('Either provide a testsuite argument or define <comment>--launch-only</comment> or <comment>--update-only</comment>'); - } - - $awsConfig = new Config(); - $awsConfig->validate(); - - $host = $this->launchInstance($output, $perTestsuite, $awsConfig, $testSuite); - - if ($launchOnly) { - return 0; - } - - $ssh = Ssh::connectToAws($host, $awsConfig->getPemFile()); - $ssh->setOutput($output); - - $testRunner = new Remote($ssh); - $testRunner->updatePiwik($gitHash); - $testRunner->replaceConfigIni(PIWIK_INCLUDE_PATH . '/plugins/TestRunner/Aws/config.ini.php'); - - if (!empty($patchFile)) { - $testRunner->applyPatch($patchFile); - } - - if ($updateOnly) { - $ssh->disconnect(); - - return 0; - } - - $testRunner->runTests($host, $testSuite, $arguments); - - $message = $this->buildFinishedMessage($testSuite, $host); - $output->writeln("\n$message\n"); - - $ssh->disconnect(); - } - - private function launchInstance(OutputInterface $output, $useOneInstancePerTestSuite, Config $awsConfig, $testSuite) - { - $awsInstance = new Instance($awsConfig, $testSuite); - - if ($useOneInstancePerTestSuite) { - $awsInstance->enableUseOneInstancePerTestSuite(); - } - - $launcher = new InstanceLauncher($awsInstance); - $host = $launcher->launchOrResumeInstance(); - - $output->writeln(sprintf("Access instance using <comment>ssh -i %s ubuntu@%s</comment>", $awsConfig->getPemFile(), $host)); - $output->writeln("You can log in to Piwik via root:secure at <comment>http://$host</comment>"); - $output->writeln("You can access database via root:secure (<comment>mysql -uroot -psecure</comment>)"); - $output->writeln("Files are located in <comment>~/www/piwik</comment>"); - $output->writeln(' '); - - return $host; - } - - private function getTestSuite(InputInterface $input) - { - $testsuite = $input->getArgument('testsuite'); - - if (!empty($testsuite) && !in_array($testsuite, $this->allowedTestSuites)) { - throw new \InvalidArgumentException('Test suite argument is wrong, use one of following: ' . implode(', ', $this->allowedTestSuites)); - } - - return $testsuite; - } - - private function getCurrentGitHash() - { - // we should not use 'git' executable unless we are in a git clone - if(!SettingsPiwik::isGitDeployment()) { - return 'WARN: it does not look like a Piwik repository clone - you must setup Piwik from git to proceed'; - } - $gitCmd = 'git -C ' . escapeshellarg(PIWIK_INCLUDE_PATH) . ' rev-parse HEAD'; - return trim(shell_exec($gitCmd)); - } - - private function buildFinishedMessage($testSuite, $host) - { - if (in_array($testSuite, array('system', 'all'))) { - $message = "<info>Tests finished. You can browse processed files and download artifacts at </info><comment>http://$host/tests/PHPUnit/System/processed/</comment>"; - } elseif ('ui' === $testSuite) { - $message = "<info>Tests finished. You can browse processed screenshots at </info><comment>http://$host/tests/UI/screenshot-diffs/diffviewer.html</comment>"; - } else { - $message = "<info>Tests finished</info>"; - } - - return $message; - } - - private function getPatchFile(InputInterface $input) - { - $file = $input->getOption('patch-file'); - - if (!empty($file) && !is_readable($file)) { - throw new \InvalidArgumentException("The patch file $file does not exist or is not readable"); - } - - return $file; - } - -} diff --git a/plugins/TestRunner/README.md b/plugins/TestRunner/README.md deleted file mode 100644 index b5ab732371..0000000000 --- a/plugins/TestRunner/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Piwik TestRunner Plugin - -## FAQ - -__Can I easily change the config for tests that run on AWS?__ - -Yes, just edit `Aws/config.ini.php` - -__I want to run the tests with different parameters on AWS, is it possible?__ - -Yes, at the time of writing this you have to edit the file `Runner/Remote.php` - -__Why am I getting an error "AWS was not able to validate the provided access credentials"?__ - -It could be caused by an invalid set date. Execute `date` on the command line and make sure it is correct. - -__How can I change the base image (AMI) that is used for AWS tests?__ - -* Log in to AWS -* Select `EC2 => AMI` -* Launch a new instance of the current AMI by selecting it and pressing `Launch` -* Select a `c3.large` instance type -* Press `Review and Launch` and on next page `Launch` (there you have to select your keypair otherwise you can't log in) -* Log in to the newly created instance. To get login information - * Go to `EC2 => Instances` - * Select the created instance - * Press `Connect` - * SSH connect example is listed there - * Make sure to use user `ubuntu` and not `root` -* Make changes on the instance -* When you are done - * Go into the home directory `cd` - * Clear the history: `cat /dev/null > ~/.bash_history && history -c` - * Execute `cd www/piwik`, then `exit`. Why? Whenever a new instance is created, those two commands will be in the history - and provides a better usability for the developer who accesses it as those two commands are most likely needed. - * Reflect the changes you did in Puppet https://github.com/piwik/piwik-dev-environment/tree/master/puppet/modules/piwik/manifests - or if you don't know Puppet at least add it in this shell script https://github.com/piwik/piwik-dev-environment/blob/master/puppet/files/setup.sh - For instance if you installed a new package you can simply add a new entry here https://github.com/piwik/piwik-dev-environment/blob/master/puppet/modules/piwik/manifests/base.pp -* In `EC2 => Instances` menu select the instance you are currently using. -* Select `Actions => Image => Create Image` -* Define the name `Piwik Testing vX.X` and a description like `Used to run Piwik tests via Piwik console`. Make sure to increase the box version in X.X (have a look in `EC2 => AMI` for current version) -* Press `Create Image` -* Go to `EC2 => AMIs` menu and while waiting for the image creation to complete add the following tags - * `Name` => `PiwikTesting` - * `Ubuntu` => Ubuntu version eg `14.04` - * `BoxVersion` => Version of the box eg `3.3` - * `PHP` => PHP Version eg `5.5` - * `MySQL` => MySQL Version eg `5.5` -* Copy the assigned AMI ID and replace the config value `[tests]aws_ami = ...` in `global.ini.php` -* Once the AMI is available trigger an `integration`, `system`, and `ui` test run using the `tests:run-aws` command to make sure everything still works -* Commit / push the new AMI-ID -* Once everything works remove the outdated AMI by selecting it and clicking `Actions => Deregister`. - -In the future once everything is completely automated we would simple create a new instance out of ((Vagrant || Docker) && Puppet) whenever we need a change but it takes a lot of time to do this and is not worth it right now. - -__How do I create a new EC2 key/pair for a developer?__ - -1. Go to: https://console.aws.amazon.com/ec2/v2/home?region=us-east-1 -2. Click `Create Key Pair` -3. Send PGP email - -``` -Here are info for running tests on Ec2 - * Access Key ID: - * Secret Access Key: - * aws_keyname = "piwik-xyz" - * PEM file content is: -``` - diff --git a/plugins/TestRunner/Runner/InstanceLauncher.php b/plugins/TestRunner/Runner/InstanceLauncher.php deleted file mode 100644 index 38cad636da..0000000000 --- a/plugins/TestRunner/Runner/InstanceLauncher.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Runner; - -use Piwik\Plugins\TestRunner\Aws\Instance; - -class InstanceLauncher { - - /** - * @var Instance - */ - private $instance; - - public function __construct(Instance $instance) - { - $this->instance = $instance; - } - - public function launchOrResumeInstance() - { - $host = $this->instance->findExisting(); - - if (empty($host)) { - $host = $this->launchInstance(); - } - - return $host; - } - - private function launchInstance() - { - $instanceIds = $this->instance->launch(); - - try { - $host = $this->instance->setup($instanceIds); - $this->instance->verifySetup($instanceIds); - } catch (\Exception $e) { - $this->instance->terminate($instanceIds); - - throw new \RuntimeException('We failed to launch a new instance so we terminated it directly. Try again! Error Message: ' . $e->getMessage()); - } - - return $host; - } - -}
\ No newline at end of file diff --git a/plugins/TestRunner/Runner/Remote.php b/plugins/TestRunner/Runner/Remote.php deleted file mode 100644 index a9911c1800..0000000000 --- a/plugins/TestRunner/Runner/Remote.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php -/** - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ - -namespace Piwik\Plugins\TestRunner\Runner; - -use \Net_SSH2; - -class Remote -{ - /** - * @var \Net_SSH2 - */ - private $ssh; - - public function __construct(Net_SSH2 $ssh) - { - $this->ssh = $ssh; - } - - public function updatePiwik($gitHash) - { - $this->ssh->exec('git reset --hard'); - $this->ssh->exec('git submodule update --init'); - $this->ssh->exec('git submodule foreach --recursive git reset --hard'); - $this->ssh->exec('git clean -d -f'); - $this->ssh->exec('git submodule foreach git clean -f'); - $this->ssh->exec('git fetch --all'); - $this->ssh->exec('git checkout ' . trim($gitHash)); - $this->ssh->exec('git submodule update --init'); - $this->ssh->exec('git submodule update --recursive --force'); - $this->ssh->exec('sudo composer.phar self-update'); - $this->ssh->exec('composer.phar install'); - } - - public function replaceConfigIni($file) - { - $content = file_get_contents($file); - - if (!empty($content)) { - $content = escapeshellarg($content); - $this->ssh->exec('echo ' . $content . ' > config/config.ini.php'); - } - } - - public function applyPatch($fileToApply) - { - $content = file_get_contents($fileToApply); - - if (!empty($content)) { - $content = escapeshellarg($content); - $this->ssh->exec('echo ' . $content . ' | git apply - '); - } - } - - public function runTests($host, $testSuite, array $arguments) - { - $this->prepareTestRun($host); - $this->printVersionInfo(); - $this->doRunTests($testSuite, $arguments); - } - - private function prepareTestRun($host) - { - $this->ssh->exec("sed -i 's/amazonAwsUrl/$host/g' ./config/config.ini.php"); - } - - private function printVersionInfo() - { - $this->ssh->exec('php --version'); - $this->ssh->exec('mysql --version'); - $this->ssh->exec('phantomjs --version'); - } - - private function doRunTests($testSuite, array $arguments) - { - $arguments = implode(' ', $arguments); - - $this->ssh->exec("ps -ef | grep \"php console tests:run\" | grep -v grep | awk '{print $2}' | xargs kill -9"); - - if ('all' === $testSuite) { - $this->ssh->exec('php console tests:run --options="--colors" ' . $arguments); - } elseif ('ui' === $testSuite) { - $this->ssh->exec('php console tests:run-ui --persist-fixture-data --assume-artifacts ' . $arguments); - } else { - $this->ssh->exec('php console tests:run --options="--colors" --testsuite="unit" ' . $arguments); - $this->ssh->exec('php console tests:run --options="--colors" --testsuite="' . $testSuite . '" ' . $arguments); - } - - if ('system' === $testSuite) { - $this->ssh->exec("tar -cjf tests/PHPUnit/System/processed/processed.tar.bz2 tests/PHPUnit/System/processed/ plugins/*/tests/System/processed/ --exclude='.gitkeep' --exclude='tests/PHPUnit/System/processed/processed.tar.bz2'"); - } - } -} diff --git a/plugins/TestRunner/screenshots/.gitkeep b/plugins/TestRunner/screenshots/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 --- a/plugins/TestRunner/screenshots/.gitkeep +++ /dev/null diff --git a/plugins/TestRunner/scripts/on_instance_launch.sh b/plugins/TestRunner/scripts/on_instance_launch.sh deleted file mode 100644 index b00dc184a3..0000000000 --- a/plugins/TestRunner/scripts/on_instance_launch.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -mkdir /tmp/ramdisk -mount -t tmpfs -o size=1536M tmpfs /tmp/ramdisk/ -mv /var/lib/mysql /tmp/ramdisk/mysql -ln -s /tmp/ramdisk/mysql/ /var/lib/mysql -chmod -R 770 /var/lib/mysql -chown -R ubuntu:ubuntu /var/lib/mysql -service mysql restart -composer-phar self-update
\ No newline at end of file |