Skip to content
Commits on Source (10)
...@@ -73,6 +73,17 @@ class Application extends BaseApplication ...@@ -73,6 +73,17 @@ class Application extends BaseApplication
parent::__construct($name, $version); parent::__construct($name, $version);
} }
/**
* Make configureIO public so we can run it before ->run()
*
* @param InputInterface $input
* @param OutputInterface $output
*/
public function configureIO(InputInterface $input, OutputInterface $output)
{
parent::configureIO($input, $output);
}
/** /**
* Initializes all the default commands. * Initializes all the default commands.
*/ */
......
...@@ -74,7 +74,7 @@ abstract class Command extends BaseCommand ...@@ -74,7 +74,7 @@ abstract class Command extends BaseCommand
try { try {
// Load context from context_name argument. // Load context from context_name argument.
$this->context_name = $this->input->getArgument('context_name'); $this->context_name = $this->input->getArgument('context_name');
$this->context = Provision::getContext($this->context_name, $this->getProvision()); $this->context = $this->getProvision()->getContext($this->context_name);
} }
catch (\Exception $e) { catch (\Exception $e) {
...@@ -96,7 +96,7 @@ abstract class Command extends BaseCommand ...@@ -96,7 +96,7 @@ abstract class Command extends BaseCommand
$this->input->setArgument('context_name', $this->context_name); $this->input->setArgument('context_name', $this->context_name);
try { try {
$this->context = Provision::getContext($this->context_name, $this->getProvision()); $this->context = $this->getProvision()->getContext($this->context_name);
} }
catch (\Exception $e) { catch (\Exception $e) {
$this->context = NULL; $this->context = NULL;
......
...@@ -153,7 +153,7 @@ class SaveCommand extends Command ...@@ -153,7 +153,7 @@ class SaveCommand extends Command
// Check for context type service requirements. // Check for context type service requirements.
$exit = FALSE; $exit = FALSE;
$this->io->comment("Checking service requirements for context type {$context_type}..."); $this->io->comment("Checking service requirements for context type {$context_type}...");
$reqs = Provision::checkServiceRequirements($context_type); $reqs = $this->getProvision()->checkServiceRequirements($context_type);
foreach ($reqs as $service => $available) { foreach ($reqs as $service => $available) {
if ($available) { if ($available) {
$this->io->successLite("Service $service: Available"); $this->io->successLite("Service $service: Available");
...@@ -352,7 +352,7 @@ class SaveCommand extends Command ...@@ -352,7 +352,7 @@ class SaveCommand extends Command
$contexts[$property] = $this->input->getOption($property); $contexts[$property] = $this->input->getOption($property);
try { try {
$context = Provision::getContext($contexts[$property]); $context = $this->getProvision()->getContext($contexts[$property]);
} }
catch (\Exception $e) { catch (\Exception $e) {
throw new \Exception("Context set by option --{$property} does not exist."); throw new \Exception("Context set by option --{$property} does not exist.");
......
...@@ -43,6 +43,7 @@ class StatusCommand extends Command ...@@ -43,6 +43,7 @@ class StatusCommand extends Command
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$this->getProvision();
if ($input->getArgument('context_name')) { if ($input->getArgument('context_name')) {
$rows = [['Configuration File', $this->context->config_path]]; $rows = [['Configuration File', $this->context->config_path]];
......
...@@ -80,7 +80,7 @@ class VerifyCommand extends Command ...@@ -80,7 +80,7 @@ class VerifyCommand extends Command
} }
*/ */
$message = $this->context->verify(); $message = $this->context->verifyCommand();
} }
} }
<?php
namespace Aegir\Provision\Common;
use Aegir\Provision\Context;
trait ContextAwareTrait
{
/**
* @var Context
*/
protected $context = NULL;
/**
* @param Context $context
*
* @return $this
*/
public function setContext(Context $context = NULL)
{
$this->context = $context;
return $this;
}
/**
* @return Context
*/
public function getContext()
{
return $this->context;
}
}
<?php
namespace Aegir\Provision\Common;
use Aegir\Provision\Context;
use Symfony\Component\Process\Process;
use Twig\Node\Expression\Unary\NegUnary;
trait ProcessAwareTrait
{
/**
* @var Process
*/
protected $process = NULL;
// /**
// * @var string
// */
// protected $command;
/**
* @param Process $process
*
* @return $this
*/
protected function setProcess(Process $process = NULL)
{
$this->process = $process;
return $this;
}
/**
* @return Process
*/
public function getProcess()
{
if (is_null($this->process)) {
$this->process = new Process($this->command);
}
return $this->process;
}
/**
* @param $command
*
* @return $this
*/
public function setCommand($command) {
$this->command = $command;
return $this;
}
/**
* @return string
*/
public function getCommand() {
return $this->command;
}
public function execute() {
$this->process->run();
}
}
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
namespace Aegir\Provision\ConfigDefinition; namespace Aegir\Provision\ConfigDefinition;
use Aegir\Provision\Application; use Aegir\Provision\Common\ProvisionAwareTrait;
use Aegir\Provision\Provision;
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition; use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
...@@ -29,6 +28,8 @@ use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; ...@@ -29,6 +28,8 @@ use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
*/ */
class ContextNodeDefinition extends ScalarNodeDefinition class ContextNodeDefinition extends ScalarNodeDefinition
{ {
use ProvisionAwareTrait;
protected function createNode() protected function createNode()
{ {
/** /**
...@@ -51,12 +52,13 @@ class ContextNodeDefinition extends ScalarNodeDefinition ...@@ -51,12 +52,13 @@ class ContextNodeDefinition extends ScalarNodeDefinition
*/ */
public function validateContext($value) public function validateContext($value)
{ {
$this->setProvision($this->getNode()->getAttribute('provision'));
// No need to do anything else. // No need to do anything else.
// If there is no context named $value, getContext() throws an exception for us. // If there is no context named $value, getContext() throws an exception for us.
Provision::getContext($value);
// If context_type is specified, Validate that the desired context is the right type. // If context_type is specified, Validate that the desired context is the right type.
if ($this->getNode()->getAttribute('context_type') && Provision::getContext($value)->type != $this->getNode()->getAttribute('context_type')) { if ($this->getNode()->getAttribute('context_type') && $this->getProvision()->getContext($value)->type != $this->getNode()->getAttribute('context_type')) {
throw new InvalidConfigurationException(strtr('The context specified for !name must be type !type.', [ throw new InvalidConfigurationException(strtr('The context specified for !name must be type !type.', [
'!name' => $this->name, '!name' => $this->name,
'!type' => $this->getNode()->getAttribute('context_type'), '!type' => $this->getNode()->getAttribute('context_type'),
...@@ -70,8 +72,8 @@ class ContextNodeDefinition extends ScalarNodeDefinition ...@@ -70,8 +72,8 @@ class ContextNodeDefinition extends ScalarNodeDefinition
$this->getNode()->getAttribute('service_requirement'): $this->getNode()->getAttribute('service_requirement'):
$path[2] $path[2]
; ;
Provision::getContext($value)->getService($service); $this->getProvision()->getContext($value)->getService($service);
} }
return $value; return $value;
} }
......
...@@ -14,6 +14,7 @@ use Robo\Common\BuilderAwareTrait; ...@@ -14,6 +14,7 @@ use Robo\Common\BuilderAwareTrait;
use Robo\Contract\BuilderAwareInterface; use Robo\Contract\BuilderAwareInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Dumper; use Symfony\Component\Yaml\Dumper;
...@@ -74,17 +75,16 @@ class Context implements BuilderAwareInterface ...@@ -74,17 +75,16 @@ class Context implements BuilderAwareInterface
*/ */
function __construct( function __construct(
$name, $name,
Provision $provision = NULL, Provision $provision,
$options = []) $options = [])
{ {
$this->name = $name; $this->name = $name;
$this->setProvision($provision);
$this->setBuilder($this->getProvision()->getBuilder());
$this->loadContextConfig($options); $this->loadContextConfig($options);
$this->prepareServices(); $this->prepareServices();
if ($provision) {
$this->setProvision($provision);
$this->setBuilder($this->getProvision()->getBuilder());
}
} }
/** /**
...@@ -126,7 +126,7 @@ class Context implements BuilderAwareInterface ...@@ -126,7 +126,7 @@ class Context implements BuilderAwareInterface
$this->config = $processor->processConfiguration($this, $configs); $this->config = $processor->processConfiguration($this, $configs);
} catch (\Exception $e) { } catch (\Exception $e) {
throw new \Exception( throw new InvalidOptionException(
strtr("There is an error with the configuration for !type '!name'. Check the file !file and try again. \n \nError: !message", [ strtr("There is an error with the configuration for !type '!name'. Check the file !file and try again. \n \nError: !message", [
'!type' => $this->type, '!type' => $this->type,
'!name' => $this->name, '!name' => $this->name,
...@@ -302,6 +302,7 @@ class Context implements BuilderAwareInterface ...@@ -302,6 +302,7 @@ class Context implements BuilderAwareInterface
->node($property, 'context') ->node($property, 'context')
->isRequired() ->isRequired()
->attribute('context_type', $type) ->attribute('context_type', $type)
->attribute('provision', $this->getProvision())
->end() ->end()
->end(); ->end();
} }
...@@ -332,7 +333,7 @@ class Context implements BuilderAwareInterface ...@@ -332,7 +333,7 @@ class Context implements BuilderAwareInterface
// If type is empty, it's because it's in the ServerContext // If type is empty, it's because it's in the ServerContext
if (empty($info['type'])) { if (empty($info['type'])) {
$server = Provision::getContext($info['server']); $server = $this->getProvision()->getContext($info['server']);
$service_type = ucfirst($server->getService($service)->type); $service_type = ucfirst($server->getService($service)->type);
} }
else { else {
...@@ -475,32 +476,33 @@ class Context implements BuilderAwareInterface ...@@ -475,32 +476,33 @@ class Context implements BuilderAwareInterface
* *
* If this context is a Service Subscriber, the provider service will be verified first. * If this context is a Service Subscriber, the provider service will be verified first.
*/ */
public function verify() { public function verifyCommand() {
$return_codes = []; $return_codes = [];
// Run verify method on all services. // Run verify method on all services.
foreach ($this->getServices() as $type => $service) { foreach ($this->getServices() as $type => $service) {
$friendlyName = $service->getFriendlyName(); $return_codes[] = $service->verify() ? 0 : 1;
if ($this->isProvider()) {
$this->getProvision()->io()->section("Verify service: {$friendlyName}");
foreach ($service->verify() as $type => $verify_success) {
$return_codes[] = $verify_success? 0: 1;
}
}
else {
$this->getProvision()->io()->section("Verify service: {$friendlyName} on {$service->provider->name}");
// First verify the service provider.
foreach ($service->verifyProvider() as $verify_part => $verify_success) {
$return_codes[] = $verify_success? 0: 1;
}
// Then run "verify" on the subscriptions.
foreach ($this->getSubscription($type)->verify() as $type => $verify_success) {
$return_codes[] = $verify_success? 0: 1;
}
}
} }
//
// if ($this->isProvider()) {
// $this->getProvision()->io()->section("Verify service: {$friendlyName}");
// foreach ($service->verify() as $type => $verify_success) {
// $return_codes[] = $verify_success? 0: 1;
// }
// }
// else {
// $this->getProvision()->io()->section("Verify service: {$friendlyName} on {$service->provider->name}");
//
// // First verify the service provider.
// foreach ($service->verifyProvider() as $verify_part => $verify_success) {
// $return_codes[] = $verify_success? 0: 1;
// }
//
// // Then run "verify" on the subscriptions.
// foreach ($this->getSubscription($type)->verify() as $type => $verify_success) {
// $return_codes[] = $verify_success? 0: 1;
// }
// }
// }
// If any service verify failed, exit with a non-zero code. // If any service verify failed, exit with a non-zero code.
if (count(array_filter($return_codes))) { if (count(array_filter($return_codes))) {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Aegir\Provision\Context; namespace Aegir\Provision\Context;
use Aegir\Provision\Application; use Aegir\Provision\Application;
use Aegir\Provision\Context;
use Aegir\Provision\ContextSubscriber; use Aegir\Provision\ContextSubscriber;
use Aegir\Provision\Provision; use Aegir\Provision\Provision;
use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\ConfigurationInterface;
...@@ -46,9 +47,9 @@ class SiteContext extends ContextSubscriber implements ConfigurationInterface ...@@ -46,9 +47,9 @@ class SiteContext extends ContextSubscriber implements ConfigurationInterface
// There is no need to check if the property exists because the config system does that. // There is no need to check if the property exists because the config system does that.
// $this->db_server = $application->getContext($this->properties['db_server']); // $this->db_server = $application->getContext($this->properties['db_server']);
$this->platform = Provision::getContext($this->properties['platform'], $provision); // Load platform context... @TODO: Automatically do this for required contexts?
$this->platform = $this->getProvision()->getContext($this->properties['platform']);
// Add platform http service subscription. // Add platform http service subscription.
$this->serviceSubscriptions['http'] = $this->platform->getSubscription('http'); $this->serviceSubscriptions['http'] = $this->platform->getSubscription('http');
$this->serviceSubscriptions['http']->context = $this; $this->serviceSubscriptions['http']->context = $this;
......
...@@ -93,6 +93,7 @@ class ContextSubscriber extends Context ...@@ -93,6 +93,7 @@ class ContextSubscriber extends Context
->node('server', 'context') ->node('server', 'context')
->isRequired() ->isRequired()
->attribute('context_type', 'server') ->attribute('context_type', 'server')
->attribute('provision', $this->getProvision())
->end() ->end()
->append($this->addServiceProperties('service_subscriptions')) ->append($this->addServiceProperties('service_subscriptions'))
->end() ->end()
......
...@@ -62,6 +62,16 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -62,6 +62,16 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
*/ */
private $commands = []; private $commands = [];
/**
* @var \Aegir\Provision\Context[]
*/
private $contexts = [];
/**
* @var array[]
*/
private $context_files = [];
/** /**
* Provision constructor. * Provision constructor.
* *
...@@ -79,16 +89,18 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -79,16 +89,18 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$this $this
->setConfig($config) ->setConfig($config)
->setInput($input)
->setOutput($output)
; ;
// Create Application. // Create Application.
$application = new Application(self::APPLICATION_NAME, self::VERSION); $application = new Application(self::APPLICATION_NAME, self::VERSION);
$application $application
->setProvision($this) ->setProvision($this)
->setLogger($logger); ->setLogger($logger)
;
$application->configureIO($input, $output);
$this->setInput($input);
$this->setOutput($output);
// Create and configure container. // Create and configure container.
$container = Robo::createDefaultContainer($input, $output, $application, $config); $container = Robo::createDefaultContainer($input, $output, $application, $config);
$this->setContainer($container); $this->setContainer($container);
...@@ -104,11 +116,51 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -104,11 +116,51 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$this->setBuilder($container->get('builder')); $this->setBuilder($container->get('builder'));
$this->setLogger($container->get('logger')); $this->setLogger($container->get('logger'));
$this->loadAllContexts();
}
/**
* Lookup all context yml files and load into Context classes.
*/
private function loadAllContexts()
{
$folder = $this->getConfig()->get('config_path') . '/provision';
$finder = new \Symfony\Component\Finder\Finder();
$finder->files()->name("*.yml")->in($folder);
foreach ($finder as $file) {
$context_type = substr($file->getFilename(), 0, strpos($file->getFilename(), '.'));
$context_name = substr($file->getFilename(), strpos($file->getFilename(), '.') + 1, strlen($file->getFilename()) - strlen($context_type) - 5);
$this->context_files[$context_name] = [
'name' => $context_name,
'type' => $context_type,
'file' => $file,
];
}
// Load Context classes from files metadata.
foreach ($this->context_files as $context) {
$class = Context::getClassName($context['type']);
$this->contexts[$context['name']] = new $class($context['name'], $this);
}
}
/**
* Loads a single context from file into $this->contexts[$name].
*
* Used to load dependant contexts that might not be instantiated yet.
*
* @param $name
*/
public function loadContext($name) {
$class = Context::getClassName($this->context_files[$name]['type']);
$this->contexts[$this->context_files[$name]['name']] = new $class($this->context_files[$name]['name'], $this);
} }
public function run(InputInterface $input, OutputInterface $output) { public function run(InputInterface $input, OutputInterface $output) {
$status_code = $this->runner->run($input, $output); $status_code = $this->runner->run($input, $output);
return $status_code; return $status_code;
} }
...@@ -186,41 +238,19 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -186,41 +238,19 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
} }
/** /**
* Load all contexts into Context objects. * Return all available contexts.
* *
* @return array * @return array|Context
*/ */
static function getAllContexts($name = '', Provision $provision = NULL) { public function getAllContexts($name = '') {
$contexts = []; if ($name && isset($this->contexts[$name])) {
$config = new Config(); return $this->contexts[$name];
$context_files = [];
$finder = new \Symfony\Component\Finder\Finder();
$finder->files()->name('*' . $name . '.yml')->in($config->get('config_path') . '/provision');
foreach ($finder as $file) {
$context_type = substr($file->getFilename(), 0, strpos($file->getFilename(), '.'));
$context_name = substr($file->getFilename(), strpos($file->getFilename(), '.') + 1, strlen($file->getFilename()) - strlen($context_type) - 5);
$context_files[$context_name] = [
'name' => $context_name,
'type' => $context_type,
'file' => $file,
];
}
foreach ($context_files as $context) {
$class = Context::getClassName($context['type']);
$contexts[$context['name']] = new $class($context['name'], $provision);
}
if ($name && isset($contexts[$name])) {
return $contexts[$name];
} }
elseif ($name && !isset($contexts[$name])) { elseif ($name && !isset($this->contexts[$name])) {
return NULL; return NULL;
} }
else { else {
return $contexts; return $this->contexts;
} }
} }
...@@ -231,9 +261,9 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -231,9 +261,9 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
* @return mixed * @return mixed
* @throws \Exception * @throws \Exception
*/ */
static public function getAllServers($service = NULL) { protected function getAllServers($service = NULL) {
$servers = []; $servers = [];
$context_files = self::getAllContexts(); $context_files = $this->getAllContexts();
if (empty($context_files)) { if (empty($context_files)) {
throw new \Exception('No server contexts found. Use `provision save` to create one.'); throw new \Exception('No server contexts found. Use `provision save` to create one.');
} }
...@@ -272,14 +302,36 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -272,14 +302,36 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
* @return array|\Aegir\Provision\Context * @return array|\Aegir\Provision\Context
* @throws \Exception * @throws \Exception
*/ */
static public function getContext($name, Provision $provision = NULL) { public function getContext($name) {
// Check if $name is empty.
if (empty($name)) {
throw new \Exception('Context name must not be empty.');
}
// If context exists but hasn't been loaded, load it.
if (empty($this->contexts[$name]) && !empty($this->context_files[$name])) {
$this->loadContext($name);
}
// Check if context still isn't found.
if (empty($this->contexts[$name])) {
throw new \Exception('Context not found with name: ' . $name);
}
return $this->contexts[$name];
}
/**
* Look for a context file being present. This is available before Context
* objects are bootstrapped.
*/
public function getContextFile($name) {
if (empty($name)) { if (empty($name)) {
throw new \Exception('Context name must not be empty.'); throw new \Exception('Context name must not be empty.');
} }
if (empty(Provision::getAllContexts($name, $provision))) { if (empty($this->context_files[$name])) {
throw new \Exception('Context not found with name: ' . $name); throw new \Exception('Context not found with name: ' . $name);
} }
return Provision::getAllContexts($name, $provision); return$this->context_files[$name];
} }
/** /**
...@@ -306,7 +358,7 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -306,7 +358,7 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
* @param $type * @param $type
* @return array * @return array
*/ */
static function checkServiceRequirements($type) { public function checkServiceRequirements($type) {
$class_name = Context::getClassName($type); $class_name = Context::getClassName($type);
// @var $context Context // @var $context Context
...@@ -315,7 +367,7 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger ...@@ -315,7 +367,7 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
$services = []; $services = [];
foreach ($service_requirements as $service) { foreach ($service_requirements as $service) {
try { try {
if (empty(Provision::getAllServers($service))) { if (empty($this->getAllServers($service))) {
$services[$service] = 0; $services[$service] = 0;
} }
else { else {
......
...@@ -8,17 +8,20 @@ ...@@ -8,17 +8,20 @@
namespace Aegir\Provision; namespace Aegir\Provision;
use Aegir\Provision\Common\ContextAwareTrait;
use Aegir\Provision\Common\ProvisionAwareTrait; use Aegir\Provision\Common\ProvisionAwareTrait;
use Psr\Log\LoggerAwareTrait;
use Robo\Common\BuilderAwareTrait; use Robo\Common\BuilderAwareTrait;
use Robo\Common\OutputAdapter; use Robo\Common\OutputAdapter;
use Robo\Contract\BuilderAwareInterface; use Robo\Contract\BuilderAwareInterface;
class Service implements BuilderAwareInterface class Service implements BuilderAwareInterface
{ {
use BuilderAwareTrait; use BuilderAwareTrait;
use ProvisionAwareTrait; use ProvisionAwareTrait;
use ContextAwareTrait;
use LoggerAwareTrait;
public $type; public $type;
public $properties; public $properties;
...@@ -46,7 +49,9 @@ class Service implements BuilderAwareInterface ...@@ -46,7 +49,9 @@ class Service implements BuilderAwareInterface
function __construct($service_config, Context $provider_context) function __construct($service_config, Context $provider_context)
{ {
$this->provider = $provider_context; $this->provider = $provider_context;
$this->setContext($provider_context);
$this->setProvision($provider_context->getProvision()); $this->setProvision($provider_context->getProvision());
$this->setLogger($provider_context->getProvision()->getLogger());
$this->type = $service_config['type']; $this->type = $service_config['type'];
$this->properties = $service_config['properties']; $this->properties = $service_config['properties'];
...@@ -77,30 +82,54 @@ class Service implements BuilderAwareInterface ...@@ -77,30 +82,54 @@ class Service implements BuilderAwareInterface
return "\Aegir\Provision\Service\\{$service}Service"; return "\Aegir\Provision\Service\\{$service}Service";
} }
} }
/**
* React to the `provision verify` command.
*/
function verify()
{
return [
'configuration' => $this->writeConfigurations(),
'service' => $this->restartService(),
];
}
/** /**
* React to `provision verify` command when run on a subscriber, to verify the service's provider. * React to the verify command. Passes off to the method verifySite, verifyServer, verifyPlatform.
* * @return mixed
* This is used to allow skipping of the service restart.
*/ */
function verifyProvider() public function verify() {
{ $method = 'verify' . ucfirst($this->getContext()->type);
return [ $this->getProvision()->getLogger()->info("Running {method}", [
'configuration' => $this->writeConfigurations(), 'method' => $method
]; ]);
return $this::$method();
} }
//
// /**
// * React to the `provision verify` command.
// */
// function verifySite()
// {
// return [
// 'configuration' => $this->writeConfigurations(),
// 'service' => $this->restartService(),
// ];
// }
//
// /**
// * React to the `provision verify` command.
// */
// function verifyPlatform()
// {
// return [
// 'configuration' => $this->writeConfigurations(),
// 'service' => $this->restartService(),
// ];
// }
//
// /**
// * React to `provision verify` command when run on a subscriber, to verify the service's provider.
// *
// * This is used to allow skipping of the service restart.
// */
// function verifyServer()
// {
// return [
// 'configuration' => $this->writeConfigurations(),
// ];
// }
/** /**
* Run the services "restart_command". * Run the services "restart_command".
* @return bool * @return bool
......
...@@ -12,6 +12,7 @@ namespace Aegir\Provision\Service; ...@@ -12,6 +12,7 @@ namespace Aegir\Provision\Service;
use Aegir\Provision\Context\SiteContext; use Aegir\Provision\Context\SiteContext;
use Aegir\Provision\Service; use Aegir\Provision\Service;
use Aegir\Provision\ServiceInterface;
use Aegir\Provision\ServiceSubscription; use Aegir\Provision\ServiceSubscription;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
...@@ -20,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface; ...@@ -20,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface;
* *
* @package Aegir\Provision\Service * @package Aegir\Provision\Service
*/ */
class DbService extends Service class DbService extends Service implements ServiceInterface
{ {
const SERVICE = 'db'; const SERVICE = 'db';
...@@ -89,7 +90,7 @@ class DbService extends Service ...@@ -89,7 +90,7 @@ class DbService extends Service
/** /**
* React to the `provision verify` command on Server contexts * React to the `provision verify` command on Server contexts
*/ */
function verify() { function verifyServer() {
$this->creds = array_map('urldecode', parse_url($this->properties['master_db'])); $this->creds = array_map('urldecode', parse_url($this->properties['master_db']));
if (!isset($this->creds['port'])) { if (!isset($this->creds['port'])) {
...@@ -135,11 +136,11 @@ class DbService extends Service ...@@ -135,11 +136,11 @@ class DbService extends Service
/** /**
* React to the `provision verify` command on subscriber contexts (sites and platforms) * React to the `provision verify` command on subscriber contexts (sites and platforms)
*/ */
function verifySubscription(ServiceSubscription $serviceSubscription) { function verifySite() {
$this->subscription = $serviceSubscription; $this->subscription = $this->getContext()->getSubscription($this->type);
// Check for database // Check for database
$this->create_site_database($serviceSubscription->context); $this->create_site_database($this->getContext());
$this->creds_root = array_map('urldecode', parse_url($this->properties['master_db'])); $this->creds_root = array_map('urldecode', parse_url($this->properties['master_db']));
...@@ -169,6 +170,10 @@ class DbService extends Service ...@@ -169,6 +170,10 @@ class DbService extends Service
} }
} }
public function verifyPlatform() {
}
/** /**
* React to `provision verify` command when run on a subscriber, to verify the service's provider. * React to `provision verify` command when run on a subscriber, to verify the service's provider.
* *
......
<?php
/**
* @file
* The Provision HttpApacheService class.
*
* @see \Provision_Service_http_apache
*/
namespace Aegir\Provision\Service\Http;
use Aegir\Provision\Robo\ProvisionCollectionBuilder;
use Aegir\Provision\Service\Http\Apache\Configuration\PlatformConfiguration;
use Aegir\Provision\Service\Http\Apache\Configuration\ServerConfiguration;
use Aegir\Provision\Service\Http\Apache\Configuration\SiteConfiguration;
use Aegir\Provision\Service\HttpService;
use Aegir\Provision\ServiceSubscription;
use Robo\Result;
use Aegir\Provision\Service\Http\Php\PhpServer;
use Symfony\Component\Process\Process;
/**
* Class HttpPhpService
*
* @package Aegir\Provision\Service\Http
*/
class HttpPhpService extends HttpService
{
const SERVICE_TYPE = 'php';
const SERVICE_TYPE_NAME = 'PHP Server';
public function verifyServer()
{
$host = $this->getContext()->getProperty('remote_host');
$port = $this->getProperty('http_port');
$this->getProvision()->getLogger()->info('Running server at {host}:{port}', [
'host' => $host,
'port' => $port,
]);
//
$this->getContext()->getBuilder()->build(PhpServer::class, ['port' => $port]);
// $server = new PhpServer($port);
/** @var PhpServer $server */
$server = $this->getContext()->getBuilder()->task(PhpServer::class, ['port' => $port]);
$server->host($host);
$server->dir(__DIR__ . '/Php/servertest');
$server->background();
$server->run();
//
$pid = $server->getProcess()->getPid();
$this->getProvision()->getLogger()->info('Server started at {host}:{port} running as process {pid}', [
'host' => $host,
'port' => $port,
'pid' => $pid,
]);
}
public function verifySite()
{
}
public function verifySubscription(ServiceSubscription $subscription)
{
print_r($subscription->context->getProperty('root'));
$this->application->getBuilder()->taskServer($this->getProperty('http_port'))
->dir('.');;
}
}
<?php
namespace Aegir\Provision\Service\Http\Php;
use Robo\Common\ExecCommand;
use Robo\Common\ExecTrait;
class PhpServer extends \Robo\Task\Development\PhpServer {
/**
* @var int
*/
protected $port;
/**
* @var string
*/
protected $host = '127.0.0.1';
/**
* @var string
*/
protected $command = 'php -S %s:%d ';
/**
* @param int $port
*/
public function __construct($port)
{
$this->port = $port;
if (strtolower(PHP_OS) === 'linux') {
$this->command = 'exec php -S %s:%d ';
}
}
/**
* @param string $host
*
* @return $this
*/
public function host($host)
{
$this->host = $host;
return $this;
}
/**
* @param string $path
*
* @return $this
*/
public function dir($path)
{
$this->command .= "-t $path";
return $this;
}
/**
* {@inheritdoc}
*/
public function getCommand()
{
return sprintf($this->command, $this->host, $this->port);
}
public function run() {
$this->executeCommand($this->getCommand());
}
public function getProcess() {
return $this->process;
}
public function task() {
}
}
\ No newline at end of file
<h1><?php print "It Works!"; ?></h1>
<p>
<?php print "This page is being generated by PHP web server." ?>
</p>
...@@ -11,6 +11,7 @@ namespace Aegir\Provision\Service; ...@@ -11,6 +11,7 @@ namespace Aegir\Provision\Service;
//require_once DRUSH_BASE_PATH . '/commands/core/rsync.core.inc'; //require_once DRUSH_BASE_PATH . '/commands/core/rsync.core.inc';
use Aegir\Provision\Service; use Aegir\Provision\Service;
use Aegir\Provision\ServiceInterface;
use Aegir\Provision\ServiceSubscription; use Aegir\Provision\ServiceSubscription;
use Consolidation\AnnotatedCommand\CommandFileDiscovery; use Consolidation\AnnotatedCommand\CommandFileDiscovery;
...@@ -19,7 +20,7 @@ use Consolidation\AnnotatedCommand\CommandFileDiscovery; ...@@ -19,7 +20,7 @@ use Consolidation\AnnotatedCommand\CommandFileDiscovery;
* *
* @package Aegir\Provision\Service * @package Aegir\Provision\Service
*/ */
class HttpService extends Service { class HttpService extends Service implements ServiceInterface {
const SERVICE = 'http'; const SERVICE = 'http';
const SERVICE_NAME = 'Web Server'; const SERVICE_NAME = 'Web Server';
...@@ -57,7 +58,7 @@ class HttpService extends Service { ...@@ -57,7 +58,7 @@ class HttpService extends Service {
* *
* This is used to allow skipping of the service restart. * This is used to allow skipping of the service restart.
*/ */
function verifyProvider() function verifyServer()
{ {
return [ return [
'configuration' => $this->writeConfigurations(), 'configuration' => $this->writeConfigurations(),
...@@ -67,14 +68,18 @@ class HttpService extends Service { ...@@ -67,14 +68,18 @@ class HttpService extends Service {
/** /**
* React to the `provision verify` command on Server contexts * React to the `provision verify` command on Server contexts
*/ */
function verifySubscription(ServiceSubscription $serviceSubscription) { function verifySite() {
$this->subscription = $serviceSubscription; $this->subscription = $this->getContext()->getSubscription();
return [ return [
'configuration' => $this->writeConfigurations($serviceSubscription), 'configuration' => $this->writeConfigurations($this->subscription),
'service' => $this->restartService(), 'service' => $this->restartService(),
]; ];
} }
//
function verifyPlatform() {
}
//
// /** // /**
// * Support the ability to cloak the database credentials using environment variables. // * Support the ability to cloak the database credentials using environment variables.
// */ // */
......
<?php
namespace Aegir\Provision;
interface ServiceInterface
{
/**
* Triggered on `provision verify` command on Site contexts.
*/
public function verifySite();
/**
* Triggered on `provision verify` command on Platform contexts.
*/
public function verifyPlatform();
/**
* Triggered on `provision verify` command on Site contexts.
*/
public function verifyServer();
}
\ No newline at end of file
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
namespace Aegir\Provision; namespace Aegir\Provision;
use Aegir\Provision\Common\ContextAwareTrait;
use Aegir\Provision\Common\ProvisionAwareTrait; use Aegir\Provision\Common\ProvisionAwareTrait;
class ServiceSubscription { class ServiceSubscription {
...@@ -20,22 +21,23 @@ class ServiceSubscription { ...@@ -20,22 +21,23 @@ class ServiceSubscription {
public $properties = []; public $properties = [];
use ProvisionAwareTrait; use ProvisionAwareTrait;
use ContextAwareTrait;
function __construct( function __construct(
Context $context, Context $context,
$server, $server,
$service_name $service_name
) { ) {
$this->context = $context; $this->setContext($context);
$this->server = Provision::getContext($server, $context->getProvision()); $this->setProvision($context->getProvision());
$this->server = $this->getProvision()->getContext($server);
$this->service = $this->server->getService($service_name); $this->service = $this->server->getService($service_name);
$this->type = $this->server->getService($service_name)->type; $this->type = $this->server->getService($service_name)->type;
if (isset($context->config['service_subscriptions'][$service_name]['properties'])) { if (isset($context->config['service_subscriptions'][$service_name]['properties'])) {
$this->properties = $context->config['service_subscriptions'][$service_name]['properties']; $this->properties = $context->config['service_subscriptions'][$service_name]['properties'];
} }
$this->setProvision($context->getProvision());
} }
public function verify() { public function verify() {
......