diff --git a/src/Mage/Command/AbstractCommand.php b/src/Mage/Command/AbstractCommand.php index 6a4c9d0..7be29d3 100644 --- a/src/Mage/Command/AbstractCommand.php +++ b/src/Mage/Command/AbstractCommand.php @@ -10,7 +10,7 @@ namespace Mage\Command; -use Mage\Runtime\Runtime; +use Mage\Runtime\RuntimeInterface; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Symfony\Component\Console\Command\Command; @@ -23,55 +23,31 @@ use Symfony\Component\Console\Command\Command; abstract class AbstractCommand extends Command { /** - * @var Runtime Current Runtime instance + * @var RuntimeInterface Current Runtime instance */ protected $runtime; /** - * @var LoggerInterface|null The instance of the logger, it's optional - */ - private $logger = null; - - /** - * Configure the Command and create the Runtime configuration + * Set the Runtime configuration * - * @param array $configuration Magallanes configuration + * @param RuntimeInterface $runtime Runtime container * @return AbstractCommand */ - public function setConfiguration($configuration) + public function setRuntime(RuntimeInterface $runtime) { - $this->runtime = new Runtime(); - $this->runtime->setConfiguration($configuration); - $this->runtime->setLogger($this->logger); + $this->runtime = $runtime; return $this; } /** - * Sets the logger - * - * @param LoggerInterface $logger - * @return AbstractCommand - */ - public function setLogger(LoggerInterface $logger = null) - { - $this->logger = $logger; - return $this; - } - - /** - * Logs a message, if logger is valid instance + * Logs a message * * @param string $message * @param string $level - * @return AbstractCommand */ public function log($message, $level = LogLevel::DEBUG) { - if ($this->logger instanceof LoggerInterface) { - $this->logger->log($level, $message); - } - - return $this; + $this->runtime->log($message, $level); } } diff --git a/src/Mage/Command/BuiltIn/DeployCommand.php b/src/Mage/Command/BuiltIn/DeployCommand.php index 8650e41..6392748 100644 --- a/src/Mage/Command/BuiltIn/DeployCommand.php +++ b/src/Mage/Command/BuiltIn/DeployCommand.php @@ -13,7 +13,7 @@ namespace Mage\Command\BuiltIn; use Mage\Runtime\Exception\DeploymentException; use Mage\Runtime\Exception\InvalidEnvironmentException; use Mage\Runtime\Exception\RuntimeException; -use Mage\Runtime\Runtime; +use Mage\Runtime\RuntimeInterface; use Mage\Task\ErrorException; use Mage\Task\ExecuteOnRollbackInterface; use Mage\Task\AbstractTask; @@ -105,7 +105,7 @@ class DeployCommand extends AbstractCommand protected function runDeployment(OutputInterface $output) { // Run Pre Deploy Tasks - $this->runtime->setStage(Runtime::PRE_DEPLOY); + $this->runtime->setStage(RuntimeInterface::PRE_DEPLOY); $preDeployTasks = $this->runtime->getTasks(); if ($this->runtime->getEnvironmentConfig('branch', false) && !$this->runtime->inRollback()) { @@ -130,7 +130,7 @@ class DeployCommand extends AbstractCommand $output->writeln(' No hosts defined, skipping On Deploy tasks'); $output->writeln(''); } else { - $this->runtime->setStage(Runtime::ON_DEPLOY); + $this->runtime->setStage(RuntimeInterface::ON_DEPLOY); $onDeployTasks = $this->runtime->getTasks(); if ($this->runtime->getEnvironmentConfig('releases', false) && !$this->runtime->inRollback()) { @@ -164,7 +164,7 @@ class DeployCommand extends AbstractCommand $output->writeln(' No hosts defined, skipping On Release tasks'); $output->writeln(''); } else { - $this->runtime->setStage(Runtime::ON_RELEASE); + $this->runtime->setStage(RuntimeInterface::ON_RELEASE); $onReleaseTasks = $this->runtime->getTasks(); if ($this->runtime->getEnvironmentConfig('releases', false)) { @@ -188,7 +188,7 @@ class DeployCommand extends AbstractCommand $output->writeln(' No hosts defined, skipping Post Release tasks'); $output->writeln(''); } else { - $this->runtime->setStage(Runtime::POST_RELEASE); + $this->runtime->setStage(RuntimeInterface::POST_RELEASE); $postReleaseTasks = $this->runtime->getTasks(); if ($this->runtime->getEnvironmentConfig('releases', false) && !$this->runtime->inRollback()) { @@ -207,7 +207,7 @@ class DeployCommand extends AbstractCommand } // Run Post Deploy Tasks - $this->runtime->setStage(Runtime::POST_DEPLOY); + $this->runtime->setStage(RuntimeInterface::POST_DEPLOY); $postDeployTasks = $this->runtime->getTasks(); if ($this->runtime->getEnvironmentConfig('releases', false) && !$this->runtime->inRollback()) { if (!in_array('deploy/targz/cleanup', $postDeployTasks)) { diff --git a/src/Mage/MageApplication.php b/src/Mage/MageApplication.php index fb6ae7a..dbbb39e 100644 --- a/src/Mage/MageApplication.php +++ b/src/Mage/MageApplication.php @@ -11,6 +11,7 @@ namespace Mage; use Mage\Command\AbstractCommand; +use Mage\Runtime\Runtime; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; @@ -28,8 +29,7 @@ use Mage\Runtime\Exception\RuntimeException; */ class MageApplication extends Application { - private $configuration; - protected $logger; + protected $runtime; /** * Configure the Magallanes Application @@ -46,14 +46,18 @@ class MageApplication extends Application $config = Yaml::parse(file_get_contents($file)); if (array_key_exists('magephp', $config)) { - $this->configuration = $config['magephp']; + $config = $config['magephp']; - if (array_key_exists('log_dir', $this->configuration)) { - $logfile = sprintf('%s/%s.log', $this->configuration['log_dir'], date('Ymd_His')); - $this->configuration['log_file'] = $logfile; + if (array_key_exists('log_dir', $config)) { + $logfile = sprintf('%s/%s.log', $config['log_dir'], date('Ymd_His')); + $config['log_file'] = $logfile; - $this->logger = new Logger('magephp'); - $this->logger->pushHandler(new StreamHandler($logfile)); + $logger = new Logger('magephp'); + $logger->pushHandler(new StreamHandler($logfile)); + + $this->runtime = new Runtime(); + $this->runtime->setConfiguration($config); + $this->runtime->setLogger($logger); } } else { throw new RuntimeException(sprintf('The file "%s" does not have a valid Magallanes configuration.', $file)); @@ -89,8 +93,7 @@ class MageApplication extends Application $command = new $class(); if ($command instanceof AbstractCommand) { - $command->setLogger($this->logger); - $command->setConfiguration($this->configuration); + $command->setRuntime($this->runtime); $this->add($command); } } diff --git a/src/Mage/Runtime/Runtime.php b/src/Mage/Runtime/Runtime.php index 1a21c78..b51af32 100644 --- a/src/Mage/Runtime/Runtime.php +++ b/src/Mage/Runtime/Runtime.php @@ -20,14 +20,8 @@ use Mage\Runtime\Exception\InvalidEnvironmentException; * * @author Andrés Montañez */ -class Runtime +class Runtime implements RuntimeInterface { - const PRE_DEPLOY = 'pre-deploy'; - const ON_DEPLOY = 'on-deploy'; - const POST_DEPLOY = 'post-deploy'; - const ON_RELEASE = 'on-release'; - const POST_RELEASE = 'post-release'; - /** * @var array Magallanes configuration */ @@ -72,7 +66,7 @@ class Runtime * Sets the Release ID * * @param string $releaseId Release ID - * @return Runtime + * @return RuntimeInterface */ public function setReleaseId($releaseId) { @@ -94,7 +88,7 @@ class Runtime * Sets the Runtime in Rollback mode On or Off * * @param bool $inRollback - * @return Runtime + * @return RuntimeInterface */ public function setRollback($inRollback) { @@ -117,7 +111,7 @@ class Runtime * * @param mixed $key Variable name * @param mixed $value Variable value - * @return Runtime + * @return RuntimeInterface */ public function setVar($key, $value) { @@ -145,7 +139,7 @@ class Runtime * Sets the Logger instance * * @param LoggerInterface $logger Logger instance - * @return Runtime + * @return RuntimeInterface */ public function setLogger(LoggerInterface $logger = null) { @@ -157,7 +151,7 @@ class Runtime * Sets the Magallanes Configuration to the Runtime * * @param array $configuration Configuration - * @return Runtime + * @return RuntimeInterface */ public function setConfiguration($configuration) { @@ -223,7 +217,7 @@ class Runtime * Sets the working Environment * * @param string $environment Environment name - * @return Runtime + * @return RuntimeInterface * @throws InvalidEnvironmentException */ public function setEnvironment($environment) @@ -250,7 +244,7 @@ class Runtime * Sets the working stage * * @param string $stage Stage code - * @return Runtime + * @return RuntimeInterface */ public function setStage($stage) { @@ -290,7 +284,7 @@ class Runtime * Sets the working Host * * @param string $host Host name - * @return Runtime + * @return RuntimeInterface */ public function setWorkingHost($host) { @@ -331,9 +325,9 @@ class Runtime public function runCommand($cmd, $timeout = 120) { switch ($this->getStage()) { - case self::ON_DEPLOY: - case self::ON_RELEASE: - case self::POST_RELEASE: + case RuntimeInterface::ON_DEPLOY: + case RuntimeInterface::ON_RELEASE: + case RuntimeInterface::POST_RELEASE: return $this->runRemoteCommand($cmd, true, $timeout); break; default: @@ -396,6 +390,11 @@ class Runtime return $this->runLocalCommand($cmdLocal, $timeout); } + /** + * Get the SSH configuration based on the environment + * + * @return array + */ public function getSSHConfig() { $sshConfig = $this->getEnvironmentConfig('ssh', ['port' => '22', 'flags' => '-q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no']); diff --git a/src/Mage/Runtime/RuntimeInterface.php b/src/Mage/Runtime/RuntimeInterface.php new file mode 100644 index 0000000..02ea63c --- /dev/null +++ b/src/Mage/Runtime/RuntimeInterface.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Mage\Runtime; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\Process\Process; +use Mage\Runtime\Exception\InvalidEnvironmentException; + +/** + * Interface for the Runtime container + * + * @author Andrés Montañez + */ +interface RuntimeInterface +{ + const PRE_DEPLOY = 'pre-deploy'; + const ON_DEPLOY = 'on-deploy'; + const POST_DEPLOY = 'post-deploy'; + const ON_RELEASE = 'on-release'; + const POST_RELEASE = 'post-release'; + + /** + * Sets the Release ID + * + * @param string $releaseId Release ID + * @return RuntimeInterface + */ + public function setReleaseId($releaseId); + + /** + * Retrieve the current Release ID + * + * @return null|string Release ID + */ + public function getReleaseId(); + + /** + * Sets the Runtime in Rollback mode On or Off + * + * @param bool $inRollback + * @return RuntimeInterface + */ + public function setRollback($inRollback); + + /** + * Indicates if Runtime is in rollback + * + * @return bool + */ + public function inRollback(); + + /** + * Sets a value in the Vars bag + * + * @param mixed $key Variable name + * @param mixed $value Variable value + * @return RuntimeInterface + */ + public function setVar($key, $value); + + /** + * Retrieve a value from the Vars bag + * + * @param mixed $key Variable name + * @param mixed $default Variable default value, returned if not found + * @return mixed + */ + public function getVar($key, $default = null); + + /** + * Sets the Logger instance + * + * @param LoggerInterface $logger Logger instance + * @return RuntimeInterface + */ + public function setLogger(LoggerInterface $logger = null); + + /** + * Sets the Magallanes Configuration to the Runtime + * + * @param array $configuration Configuration + * @return RuntimeInterface + */ + public function setConfiguration($configuration); + + /** + * Retrieve the Configuration + * + * @return array + */ + public function getConfiguration(); + + /** + * Retrieves the Configuration options for a specific section in the configuration + * + * @param mixed $key Section name + * @param mixed $default Default value + * @return mixed + */ + public function getConfigOptions($key, $default = null); + + /** + * Returns the configuration for the current Environment + * If $key is provided, it will be returned only that section, if not found the default value will be returned, + * if $key is not provided, the whole Environment's configuration will be returned + * + * @param mixed $key Section name + * @param mixed $default Default value + * @return mixed + * @throws InvalidEnvironmentException + */ + public function getEnvironmentConfig($key = null, $default = null); + + /** + * Sets the working Environment + * + * @param string $environment Environment name + * @return RuntimeInterface + * @throws InvalidEnvironmentException + */ + public function setEnvironment($environment); + + /** + * Returns the current working Environment + * + * @return null|string + */ + public function getEnvironment(); + + /** + * Sets the working stage + * + * @param string $stage Stage code + * @return RuntimeInterface + */ + public function setStage($stage); + + /** + * Retrieve the current wokring Stage + * + * @return string + */ + public function getStage(); + + /** + * Retrieve the defined Tasks for the current Environment and Stage + * + * @return array + * @throws InvalidEnvironmentException + */ + public function getTasks(); + + /** + * Sets the working Host + * + * @param string $host Host name + * @return RuntimeInterface + */ + public function setWorkingHost($host); + + /** + * Retrieve the working Host + * + * @return null|string + */ + public function getWorkingHost(); + + /** + * Logs a Message into the Logger + * + * @param string $message Log message + * @param string $level Log Level + */ + public function log($message, $level = LogLevel::DEBUG); + + /** + * Executes a command, it will be run Locally or Remotely based on the working Stage + * + * @param string $cmd Command to execute + * @param int $timeout Seconds to wait + * @return Process + */ + public function runCommand($cmd, $timeout = 120); + + /** + * Execute a command locally + * + * @param string $cmd Command to execute + * @param int $timeout Seconds to wait + * @return Process + */ + public function runLocalCommand($cmd, $timeout = 120); + + /** + * Executes a command remotely, if jail is true, it will run inside the Host Path and the Release (if available) + * + * @param string $cmd Command to execute + * @param bool $jail Jail the command + * @param int $timeout Seconds to wait + * @return Process + * @throws InvalidEnvironmentException + */ + public function runRemoteCommand($cmd, $jail = true, $timeout = 120); + + /** + * Get the SSH configuration based on the environment + * + * @return array + */ + public function getSSHConfig(); +} diff --git a/src/Mage/Task/AbstractTask.php b/src/Mage/Task/AbstractTask.php index 0ee7c2f..6cad351 100644 --- a/src/Mage/Task/AbstractTask.php +++ b/src/Mage/Task/AbstractTask.php @@ -10,7 +10,7 @@ namespace Mage\Task; -use Mage\Runtime\Runtime; +use Mage\Runtime\RuntimeInterface; /** * Abstract base class for Magallanes Tasks @@ -25,7 +25,7 @@ abstract class AbstractTask protected $options = []; /** - * @var Runtime + * @var RuntimeInterface */ protected $runtime; @@ -68,10 +68,10 @@ abstract class AbstractTask /** * Set the Runtime instance * - * @param Runtime $runtime + * @param RuntimeInterface $runtime * @return AbstractTask */ - public function setRuntime(Runtime $runtime) + public function setRuntime(RuntimeInterface $runtime) { $this->runtime = $runtime; return $this; diff --git a/src/Mage/Task/TaskFactory.php b/src/Mage/Task/TaskFactory.php index d1d7af4..e046436 100644 --- a/src/Mage/Task/TaskFactory.php +++ b/src/Mage/Task/TaskFactory.php @@ -10,7 +10,7 @@ namespace Mage\Task; -use Mage\Runtime\Runtime; +use Mage\Runtime\RuntimeInterface; use Mage\Runtime\Exception\RuntimeException; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; @@ -23,7 +23,7 @@ use Symfony\Component\Finder\SplFileInfo; class TaskFactory { /** - * @var Runtime + * @var RuntimeInterface */ protected $runtime; @@ -35,9 +35,9 @@ class TaskFactory /** * Constructor * - * @param Runtime $runtime + * @param RuntimeInterface $runtime */ - public function __construct(Runtime $runtime) + public function __construct(RuntimeInterface $runtime) { $this->runtime = $runtime; $this->loadBuiltInTasks(); diff --git a/src/Mage/Utils.php b/src/Mage/Utils.php index e82dc44..6c1bd9a 100644 --- a/src/Mage/Utils.php +++ b/src/Mage/Utils.php @@ -10,7 +10,7 @@ namespace Mage; -use Mage\Runtime\Runtime; +use Mage\Runtime\RuntimeInterface; use DateTime; /** @@ -29,23 +29,23 @@ class Utils public static function getStageName($stage) { switch ($stage) { - case Runtime::PRE_DEPLOY: + case RuntimeInterface::PRE_DEPLOY: return 'Pre Deployment'; break; - case Runtime::ON_DEPLOY: + case RuntimeInterface::ON_DEPLOY: return 'On Deployment'; break; - case Runtime::POST_DEPLOY: + case RuntimeInterface::POST_DEPLOY: return 'Post Deployment'; break; - case Runtime::ON_RELEASE: + case RuntimeInterface::ON_RELEASE: return 'On Release'; break; - case Runtime::POST_RELEASE: + case RuntimeInterface::POST_RELEASE: return 'Post Release'; break; }