summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Pugh2017-11-02 13:40:13 (GMT)
committerJon Pugh2017-11-02 13:40:13 (GMT)
commitc8625f1709b15c23f6d42748892eab874c37491f (patch)
tree13a2a977eedfb9d880e80376afe09094d20e0984
parent1c68f8dfc4ea9cbfc04d252ceba9688d9c401a20 (diff)
parent0167b2130c3d5f0447179fd02988f274d2ce72d0 (diff)
Merge branch '4.x-services' of git.drupal.org:project/provision into 4.x-services4.x-services
-rw-r--r--bin/provision.php2
-rw-r--r--composer.json1
-rw-r--r--composer.lock2
-rw-r--r--src/Application.php86
-rw-r--r--src/Command.php2
-rw-r--r--src/Command/SaveCommand.php9
-rw-r--r--src/Command/ServicesCommand.php57
-rw-r--r--src/Context.php265
-rw-r--r--src/Context/PlatformContext.php39
-rw-r--r--src/Context/ServerContext.php199
-rw-r--r--src/Context/SiteContext.php38
-rw-r--r--src/Service.php51
-rw-r--r--src/Service/DbService.php31
-rw-r--r--src/Service/Http/Apache/Configuration/PlatformConfiguration.php12
-rw-r--r--src/Service/Http/Apache/Configuration/SiteConfiguration.php18
-rw-r--r--src/Service/HttpService.php25
-rw-r--r--src/ServiceSubscription.php25
17 files changed, 598 insertions, 264 deletions
diff --git a/bin/provision.php b/bin/provision.php
index 39dbc02..1a0f3aa 100644
--- a/bin/provision.php
+++ b/bin/provision.php
@@ -54,7 +54,7 @@ if ($debug){
}
try {
- $application = new Application();
+ $application = new Application($input, $output);
$application->run();
}
catch (\Exception $e) {
diff --git a/composer.json b/composer.json
index c3f078d..2d63c44 100644
--- a/composer.json
+++ b/composer.json
@@ -8,6 +8,7 @@
"require": {
"consolidation/annotated-command": "~2",
"drupal/console-core": "1.0.2",
+ "psr/log": "^1.0",
"psy/psysh": "^0.8.11",
"symfony/console": "^3.3",
"symfony/yaml": "^3.3"
diff --git a/composer.lock b/composer.lock
index 02c47ed..fe25733 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "c8f06b1cc28f9638bdc92415ed78c328",
+ "content-hash": "25f4161ac19dde865bcef9fa9d341b03",
"packages": [
{
"name": "consolidation/annotated-command",
diff --git a/src/Application.php b/src/Application.php
index 3008df8..0d297b3 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -8,11 +8,14 @@ use Aegir\Provision\Command\ShellCommand;
use Aegir\Provision\Command\StatusCommand;
use Aegir\Provision\Command\VerifyCommand;
use Aegir\Provision\Console\Config;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputDefinition;
+use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application as BaseApplication;
@@ -49,10 +52,26 @@ class Application extends BaseApplication
* @var string
*/
const DEFAULT_TIMEZONE = 'America/New_York';
-
- public function __construct()
+
+ /**
+ * @var LoggerInterface
+ */
+ public $logger;
+
+ /**
+ * Application constructor.
+ *
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ *
+ * @throws \Exception
+ */
+ public function __construct(InputInterface $input, OutputInterface $output)
{
-
+ $this->logger = new ConsoleLogger($output,
+ [LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL]
+ );
+
// If no timezone is set, set Default.
if (empty(ini_get('date.timezone'))) {
date_default_timezone_set($this::DEFAULT_TIMEZONE);
@@ -105,7 +124,7 @@ class Application extends BaseApplication
$commands[] = new ListCommand();
$commands[] = new SaveCommand();
$commands[] = new ServicesCommand();
- $commands[] = new ShellCommand();
+// $commands[] = new ShellCommand();
$commands[] = new StatusCommand();
$commands[] = new VerifyCommand();
@@ -137,16 +156,22 @@ class Application extends BaseApplication
*
* @return array
*/
- function getAllContexts() {
+ function getAllContexts($name = '') {
$contexts = [];
$finder = new \Symfony\Component\Finder\Finder();
- $finder->files()->name('*.yml')->in($this->config->get('config_path') . '/provision');
+ $finder->files()->name('*' . $name . '.yml')->in($this->config->get('config_path') . '/provision');
foreach ($finder as $file) {
list($context_type, $context_name) = explode('.', $file->getFilename());
$class = '\Aegir\Provision\Context\\' . ucfirst($context_type) . "Context";
- $contexts[$context_name] = new $class($context_name, $this->config->all());
+ $contexts[$context_name] = new $class($context_name, $this->config->all(), $this);
+ }
+
+ if ($name) {
+ return $contexts[$name];
+ }
+ else {
+ return $contexts;
}
- return $contexts;
}
/**
@@ -158,9 +183,50 @@ class Application extends BaseApplication
* @throws \Exception
*/
function getContext($name) {
- if (empty($this->getAllContexts()[$name])) {
+ if (empty($this->getAllContexts($name))) {
throw new \Exception('Context not found with name: ' . $name);
}
- return $this->getAllContexts()[$name];
+ return $this->getAllContexts($name);
+ }
+
+
+ /**
+ * Load all server contexts.
+ *
+ * @param null $service
+ * @return mixed
+ * @throws \Exception
+ */
+ public function getAllServers($service = NULL) {
+ $servers = [];
+ $contexts = $this->getAllContexts();
+ if (empty($contexts)) {
+ throw new \Exception('No contexts found. Use `provision save` to create one.');
+ }
+
+ foreach ($contexts as $name => &$context) {
+ if ($context->type == 'server') {
+ $servers[$name] = $context;
+ }
+ }
+ return $servers;
+ }
+
+ /**
+ * Get a simple array of all servers, optionally specifying the the service_type to filter by ("http", "db" etc.)
+ * @param string $service_type
+ * @return array
+ */
+ public function getServerOptions($service_type = '') {
+ $servers = [];
+ foreach ($this->getAllServers() as $server) {
+ if ($service_type && !empty($server->config['services'][$service_type])) {
+ $servers[$server->name] = $server->name . ': ' . $server->config['services'][$service_type]['type'];
+ }
+ elseif ($service_type == '') {
+ $servers[$server->name] = $server->name . ': ' . $server->config['services'][$service_type]['type'];
+ }
+ }
+ return $servers;
}
}
diff --git a/src/Command.php b/src/Command.php
index 9ced4f1..4cf83fc 100644
--- a/src/Command.php
+++ b/src/Command.php
@@ -3,9 +3,11 @@
namespace Aegir\Provision;
use Drupal\Console\Core\Style\DrupalStyle;
+use Psr\Log\LogLevel;
use Symfony\Component\Console\Command\Command as BaseCommand;
use Drupal\Console\Core\Command\Shared\CommandTrait;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface;
/**
diff --git a/src/Command/SaveCommand.php b/src/Command/SaveCommand.php
index 0ba0aa3..bbff324 100644
--- a/src/Command/SaveCommand.php
+++ b/src/Command/SaveCommand.php
@@ -68,7 +68,7 @@ class SaveCommand extends Command
);
// Load all Aegir\Provision\Context and inject their options.
- // @TODO: Figure out a way to do discovery to include all classes that inherit Aegir\Provision\Context
+ // @TODO: Use CommandFileDiscovery to include all classes that inherit Aegir\Provision\Context
$contexts[] = SiteContext::option_documentation();
$contexts[] = PlatformContext::option_documentation();
$contexts[] = ServerContext::option_documentation();
@@ -113,7 +113,7 @@ class SaveCommand extends Command
}
$properties = $this->askForContextProperties();
$class = Context::getClassName($this->input->getOption('context_type'));
- $this->context = new $class($input->getArgument('context_name'), $this->getApplication()->getConfig()->all(), $properties);
+ $this->context = new $class($input->getArgument('context_name'), $this->getApplication()->getConfig()->all(), $this->getApplication(), $properties);
}
// Delete context config.
@@ -144,11 +144,6 @@ class SaveCommand extends Command
$this->io->error("Unable to save configuration to {$this->context->config_path}. ");
}
}
-
- $output->writeln(
- "Context Object: ".print_r($this->context,1)
- );
-
// $command = 'drush provision-save '.$input->getArgument('context_name');
// $this->process($command);
}
diff --git a/src/Command/ServicesCommand.php b/src/Command/ServicesCommand.php
index 89baac1..a0a3699 100644
--- a/src/Command/ServicesCommand.php
+++ b/src/Command/ServicesCommand.php
@@ -8,6 +8,7 @@ use Aegir\Provision\Context\PlatformContext;
use Aegir\Provision\Context\ServerContext;
use Aegir\Provision\Context\SiteContext;
use Consolidation\AnnotatedCommand\CommandFileDiscovery;
+use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputDefinition;
@@ -81,9 +82,9 @@ class ServicesCommand extends Command
$input,
$output
);
- if (isset($this->context->type) && $this->context->type != 'server') {
- throw new \Exception('Context must be a server.');
- }
+// if (isset($this->context->type) && $this->context->type != 'server') {
+// throw new \Exception('Context must be a server.');
+// }
$this->sub_command = $input->getArgument('sub_command');
}
@@ -120,19 +121,50 @@ class ServicesCommand extends Command
$this->io->comment("Add Services");
$service = $this->io->choice('Which service?', $this->context->getServiceOptions());
- // Then ask which service type
- $service_type = $this->io->choice('Which service type?', $this->context->getServiceTypeOptions($service));
- // Then ask for all options.
- $properties = $this->askForServiceProperties($service);
+ // If server, ask which service type.
+ if ($this->context->type == 'server') {
+ if (empty($this->context->getServiceTypeOptions($service))) {
+ throw new \Exception("There was no class found for service $service. Create one named \\Aegir\\Provision\\Service\\{$service}Service");
+ }
+
+ $service_type = $this->io->choice('Which service type?', $this->context->getServiceTypeOptions($service));
+
+ // Then ask for all options.
+ $properties = $this->askForServiceProperties($service);
- $this->io->info("Adding $service service $service_type...");
+ $this->io->info("Adding $service service $service_type...");
- try {
- $this->context->config['services'][$service] = [
+ $services_key = 'services';
+ $service_info = [
'type' => $service_type,
- 'properties' => $properties,
];
+ }
+ // All other context types are associating with servers that provide the service.
+ else {
+ if (empty($this->getApplication()->getServerOptions($service))) {
+ throw new \Exception("No servers providing $service service were found. Create one with `provision save` or use `provision services` to add to an existing server.");
+ }
+
+ $server = $this->io->choice('Which server?', $this->getApplication()->getServerOptions($service));
+
+ // Then ask for all options.
+ $server_context = $this->getApplication()->getContext($server);
+ $properties = $this->askForServiceProperties($service);
+
+ $this->io->info("Using $service service from server $server...");
+
+ $services_key = 'service_subscriptions';
+ $service_info = [
+ 'server' => $server,
+ ];
+ }
+
+ try {
+ $this->context->config[$services_key][$service] = $service_info;
+ if (!empty($properties)) {
+ $this->context->config[$services_key][$service]['properties'] = $properties;
+ }
$this->context->save();
$this->io->success('Service saved to Context!');
}
@@ -149,8 +181,9 @@ class ServicesCommand extends Command
private function askForServiceProperties($service) {
$class = $this->context->getAvailableServices($service);
+ $method = "{$this->context->type}_options";
- $options = $class::option_documentation();
+ $options = $class::{$method}();
$properties = [];
foreach ($options as $name => $description) {
// If option does not exist, ask for it.
diff --git a/src/Context.php b/src/Context.php
index 7237efb..282d6d1 100644
--- a/src/Context.php
+++ b/src/Context.php
@@ -6,6 +6,9 @@
namespace Aegir\Provision;
+use Consolidation\AnnotatedCommand\CommandFileDiscovery;
+use Drupal\Console\Core\Style\DrupalStyle;
+use Psr\Log\LoggerInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Filesystem\Exception\IOException;
@@ -50,16 +53,34 @@ class Context
protected $properties = [];
/**
+ * @var array
+ * A list of services associated with this context.
+ */
+ protected $services = [];
+
+ /**
+ * @var \Aegir\Provision\Application;
+ */
+ public $application;
+
+ /**
+ * @var LoggerInterface
+ */
+ public $logger;
+
+ /**
* Context constructor.
*
* @param $name
* @param $console_config
* @param array $options
*/
- function __construct($name, $console_config, $options = [])
+ function __construct($name, $console_config, Application $application, $options = [])
{
$this->name = $name;
+ $this->application = $application;
$this->loadContextConfig($console_config, $options);
+ $this->prepareServices();
}
/**
@@ -100,12 +121,141 @@ class Context
}
/**
+ * Load Service classes from config into Context..
+ */
+ protected function prepareServices() {
+ if (isset($this->config['services'])) {
+
+ foreach ($this->config['services'] as $service_name => $service) {
+ $service_name = ucfirst($service_name);
+ $service_type = ucfirst($service['type']);
+ $service_class = "\\Aegir\\Provision\\Service\\{$service_name}\\{$service_name}{$service_type}Service";
+ $this->services[strtolower($service_name)] = new $service_class($service, $this);
+ }
+ }
+ elseif (isset($this->config['service_subscriptions'])) {
+ foreach ($this->config['service_subscriptions'] as $service_name => $service) {
+ $this->servers[$service_name] = $server = $this->application->getContext($service['server']);
+ $this->services[$service_name] = new ServiceSubscription($this, $server, $service_name);
+ }
+ }
+ else {
+ $this->services = [];
+ }
+ }
+
+ /**
+ * Loads all available \Aegir\Provision\Service classes
+ *
+ * @return array
+ */
+ public function getAvailableServices($service = '') {
+
+ // Load all service classes
+ $classes = [];
+ $discovery = new CommandFileDiscovery();
+ $discovery->setSearchPattern('*Service.php');
+ $servicesFiles = $discovery->discover(__DIR__ .'/Service', '\Aegir\Provision\Service');
+ foreach ($servicesFiles as $serviceClass) {
+ // If this is a server, show all services. If it is not, but service allows this type of context, load it.
+ if ($this->type == 'server' || in_array($this->type, $serviceClass::allowedContexts())) {
+ $classes[$serviceClass::SERVICE] = $serviceClass;
+ }
+ }
+
+ if ($service && isset($classes[$service])) {
+ return $classes[$service];
+ }
+ elseif ($service && !isset($classes[$service])) {
+ throw new \Exception("No service with name $service was found.");
+ }
+ else {
+ return $classes;
+ }
+ }
+
+ /**
+ * Lists all available services as a simple service => name array.
+ * @return array
+ */
+ public function getServiceOptions() {
+ $options = [];
+ $services = $this->getAvailableServices();
+ foreach ($services as $service => $class) {
+ $options[$service] = $class::SERVICE_NAME;
+ }
+ return $options;
+ }
+
+ /**
+ * @return array
+ */
+ protected function getAvailableServiceTypes($service, $service_type = NULL) {
+
+ // Load all service classes
+ $classes = [];
+ $discovery = new CommandFileDiscovery();
+ $discovery->setSearchPattern(ucfirst($service) . '*Service.php');
+ $serviceTypesFiles = $discovery->discover(__DIR__ .'/Service/' . ucfirst($service), '\Aegir\Provision\Service\\' . ucfirst($service));
+ foreach ($serviceTypesFiles as $serviceTypeClass) {
+ $classes[$serviceTypeClass::SERVICE_TYPE] = $serviceTypeClass;
+ }
+
+ if ($service_type && isset($classes[$service_type])) {
+ return $classes[$service_type];
+ }
+ elseif ($service_type && !isset($classes[$service_type])) {
+ throw new \Exception("No service type with name $service_type was found.");
+ }
+ else {
+ return $classes;
+ }
+ }
+
+ /**
+ * Lists all available services as a simple service => name array.
+ * @return array
+ */
+ public function getServiceTypeOptions($service) {
+ $options = [];
+ $service_types = $this->getAvailableServiceTypes($service);
+ foreach ($service_types as $service_type => $class) {
+ $options[$service_type] = $class::SERVICE_TYPE_NAME;
+ }
+ return $options;
+ }
+
+
+ /**
+ * Return all services for this context.
+ *
+ * @return array
+ */
+ public function getServices() {
+ return $this->services;
+ }
+
+ /**
+ * Return all services for this context.
+ *
+ * @return array
+ */
+ public function getService($type) {
+ if (isset($this->services[$type])) {
+ return $this->services[$type];
+ }
+ else {
+ throw new \Exception("Service '$type' does not exist.");
+ }
+ }
+
+ /**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$tree_builder = new TreeBuilder();
- $root_node = $tree_builder->root('server');
+ $root_node = $tree_builder->root($this->type);
$root_node
->children()
->scalarNode('name')
@@ -113,6 +263,28 @@ class Context
->end()
->end();
+ // Load Services
+ if ($this->type == 'server') {
+ $services_key = 'services';
+ $services_property = 'type';
+ }
+ else {
+ $services_key = 'service_subscriptions';
+ $services_property = 'server';
+ }
+
+ $root_node
+ ->children()
+ ->arrayNode($services_key)
+ ->prototype('array')
+ ->children()
+ ->scalarNode($services_property)
+ ->isRequired(true)
+ ->end()
+ ->append($this->addServiceProperties($services_key))
+ ->end()
+ ->end();
+
// @TODO: Figure out how we can let other classes add to Context properties.
foreach ($this->option_documentation() as $name => $description) {
$root_node
@@ -131,6 +303,77 @@ class Context
}
/**
+ * Append Service class options_documentation to config tree.
+ */
+ public function addServiceProperties($property_name = 'services')
+ {
+ $builder = new TreeBuilder();
+ $node = $builder->root('properties');
+
+ // Load config tree from Service type classes
+ if (!empty($this->getProperty($property_name)) && !empty($this->getProperty($property_name))) {
+ foreach ($this->getProperty($property_name) as $service => $info) {
+
+ // If type is empty, it's because it's in the ServerContext
+ if (empty($info['type'])) {
+ $server = $this->application->getContext($info['server']);
+ $service_type = ucfirst($server->getService($service)->type);
+ }
+ else {
+ $service_type = ucfirst($info['type']);
+ }
+ $service = ucfirst($service);
+ $class = "\Aegir\Provision\Service\\{$service}\\{$service}{$service_type}Service";
+ $method = "{$this->type}_options";
+
+ foreach ($class::{$method}() as $name => $description) {
+ $node
+ ->children()
+ ->scalarNode($name)->end()
+ ->end()
+ ->end();
+ }
+ }
+ }
+ return $node;
+ }
+
+ /**
+ * Output a list of all services for this context.
+ */
+ public function showServices(DrupalStyle $io) {
+ if (!empty($this->getServices())) {
+ $is_server = $this->type == 'server';
+ $rows = [];
+
+ $headers = $is_server?
+ ['Services']:
+ ['Service', 'Server', 'Type'];
+
+ foreach ($this->getServices() as $name => $service) {
+ if ($is_server) {
+ $rows[] = [$name, $service->type];
+ }
+ else {
+ $rows[] = [
+ $name,
+ $service->server->name,
+ $service->server->getService($name)->type
+ ];
+ }
+
+ // Show all properties.
+ if (!empty($service->properties )) {
+ foreach ($service->properties as $name => $value) {
+ $rows[] = [' ' . $name, $value];
+ }
+ }
+ }
+ $io->table($headers, $rows);
+ }
+ }
+
+ /**
* Return all properties for this context.
*
* @return array
@@ -194,7 +437,23 @@ class Context
return '\Aegir\Provision\Context\\' . ucfirst($type) . "Context";
}
+// public function verify() {
+// return "Provision Context";
+// }
+
+ /**
+ * Verify this context.
+ *
+ * Running `provision verify CONTEXT` triggers this method.
+ *
+ * Collect all services for the context and run the verify() method on them
+ */
public function verify() {
- return "Provision Context";
+
+ // Run verify method on all services.
+ foreach ($this->getServices() as $service) {
+ $service->verify();
+ }
}
+
}
diff --git a/src/Context/PlatformContext.php b/src/Context/PlatformContext.php
index e5f0f03..d15abdb 100644
--- a/src/Context/PlatformContext.php
+++ b/src/Context/PlatformContext.php
@@ -2,7 +2,9 @@
namespace Aegir\Provision\Context;
+use Aegir\Provision\Application;
use Aegir\Provision\Context;
+use Aegir\Provision\Service\Http\Apache\Configuration\PlatformConfiguration;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
@@ -18,7 +20,35 @@ class PlatformContext extends Context implements ConfigurationInterface
* @var string
*/
public $type = 'platform';
-
+
+ /**
+ * @var \Aegir\Provision\Context\ServerContext;
+ */
+ public $web_server;
+
+ /**
+ * PlatformContext constructor.
+ *
+ * @param $name
+ * @param $console_config
+ * @param Application $application
+ * @param array $options
+ */
+ function __construct($name, $console_config, Application $application, array $options = [])
+ {
+ parent::__construct($name, $console_config, $application, $options);
+
+ // Load "web_server" context.
+ if (isset($this->config['web_server'])) {
+ $this->web_server = $application->getContext($this->config['web_server']);
+ $this->web_server->logger = $application->logger;
+
+ }
+ else {
+ throw new \Exception('No web_server found.');
+ }
+ }
+
static function option_documentation()
{
$options = [
@@ -31,4 +61,11 @@ class PlatformContext extends Context implements ConfigurationInterface
return $options;
}
+
+// @TODO: Remove. This should be handled by Services now.
+// public function verify() {
+// parent::verify();
+// $this->logger->info('Verifying Web Server...');
+// $this->web_server->verify();
+// }
}
diff --git a/src/Context/ServerContext.php b/src/Context/ServerContext.php
index 61c5e67..07f375b 100644
--- a/src/Context/ServerContext.php
+++ b/src/Context/ServerContext.php
@@ -2,6 +2,7 @@
namespace Aegir\Provision\Context;
+use Aegir\Provision\Application;
use Aegir\Provision\Context;
use Consolidation\AnnotatedCommand\CommandFileDiscovery;
use Drupal\Console\Core\Style\DrupalStyle;
@@ -23,42 +24,6 @@ class ServerContext extends Context implements ConfigurationInterface
*/
public $type = 'server';
- /**
- * @var array
- * A list of services needed for this context.
- */
- protected $services = [];
-
- /**
- * ServerContext constructor.
- *
- * @param $name
- * @param $console_config
- * @param array $options
- */
- function __construct($name, $console_config, array $options = [])
- {
- parent::__construct($name, $console_config, $options);
- if (isset($this->config['services'])) {
- $this->prepareServices();
- }
- else {
- $this->services = [];
- }
- }
-
- /**
- * Load Service classes from config into Context..
- */
- protected function prepareServices() {
- foreach ($this->config['services'] as $service_name => $service) {
- $service_name = ucfirst($service_name);
- $service_type = ucfirst($service['type']);
- $service_class = "\\Aegir\\Provision\\Service\\{$service_name}\\{$service_name}{$service_type}Service";
- $this->services[strtolower($service_name)] = new $service_class($service, $this);
- }
- }
-
static function option_documentation()
{
$options = [
@@ -71,166 +36,4 @@ class ServerContext extends Context implements ConfigurationInterface
return $options;
}
- /**
- * Loads all available \Aegir\Provision\Service classes
- *
- * @return array
- */
- public function getAvailableServices($service = NULL) {
-
- // Load all service classes
- $classes = [];
- $discovery = new CommandFileDiscovery();
- $discovery->setSearchPattern('*Service.php');
- $servicesFiles = $discovery->discover(__DIR__ .'/../Service', '\Aegir\Provision\Service');
-
- foreach ($servicesFiles as $serviceClass) {
- $classes[$serviceClass::SERVICE] = $serviceClass;
- }
-
- if ($service && isset($classes[$service])) {
- return $classes[$service];
- }
- elseif ($service && !isset($classes[$service])) {
- throw new \Exception("No service with name $service was found.");
- }
- else {
- return $classes;
- }
- }
-
- /**
- * Lists all available services as a simple service => name array.
- * @return array
- */
- public function getServiceOptions() {
- $options = [];
- $services = $this->getAvailableServices();
- foreach ($services as $service => $class) {
- $options[$service] = $class::SERVICE_NAME;
- }
- return $options;
- }
-
- /**
- * @return array
- */
- protected function getAvailableServiceTypes($service, $service_type = NULL) {
-
- // Load all service classes
- $classes = [];
- $discovery = new CommandFileDiscovery();
- $discovery->setSearchPattern(ucfirst($service) . '*Service.php');
- $serviceTypesFiles = $discovery->discover(__DIR__ .'/../Service/' . ucfirst($service), '\Aegir\Provision\Service\\' . ucfirst($service));
- foreach ($serviceTypesFiles as $serviceTypeClass) {
- $classes[$serviceTypeClass::SERVICE_TYPE] = $serviceTypeClass;
- }
-
- if ($service_type && isset($classes[$service_type])) {
- return $classes[$service_type];
- }
- elseif ($service_type && !isset($classes[$service_type])) {
- throw new \Exception("No service type with name $service_type was found.");
- }
- else {
- return $classes;
- }
- }
-
- /**
- * Lists all available services as a simple service => name array.
- * @return array
- */
- public function getServiceTypeOptions($service) {
- $options = [];
- $service_types = $this->getAvailableServiceTypes($service);
- foreach ($service_types as $service_type => $class) {
- $options[$service_type] = $class::SERVICE_TYPE_NAME;
- }
- return $options;
- }
-
-
- /**
- * Return all services for this context.
- *
- * @return array
- */
- public function getServices() {
- return $this->services;
- }
-
- /**
- * Pass server specific config to Context configTreeBuilder.
- */
- public function configTreeBuilder(&$root_node)
- {
- $root_node
- ->children()
- ->arrayNode('services')
- ->prototype('array')
- ->children()
- ->scalarNode('type')
- ->isRequired(true)
- ->end()
- ->append($this->addServiceProperties())
- ->end()
- ->end();
- }
-
- /**
- * Append Service class options_documentation to config tree.
- */
- public function addServiceProperties()
- {
- $builder = new TreeBuilder();
- $node = $builder->root('properties');
-
- // Load config tree from Service type classes
- if (!empty($this->getProperty('services')) && !empty($this->getProperty('services'))) {
- foreach ($this->getProperty('services') as $service => $info) {
- $service = ucfirst($service);
- $service_type = ucfirst($info['type']);
- $class = "\Aegir\Provision\Service\\{$service}\\{$service}{$service_type}Service";
- foreach ($class::option_documentation() as $name => $description) {
- $node
- ->children()
- ->scalarNode($name)->end()
- ->end()
- ->end();
- }
- }
- }
- return $node;
- }
-
- public function verify() {
-
- // Run verify method on all services.
- foreach ($this->getServices() as $service) {
- $service->verify();
- }
-
- return "Server Context Verified: " . $this->name;
- }
-
- /**
- * Output a list of all services for this service.
- */
- public function showServices(DrupalStyle $io) {
- if (!empty($this->getServices())) {
- $rows = [];
- foreach ($this->getServices() as $name => $service) {
- $rows[] = [$name, $service->type];
-
- // Show all properties.
- if (!empty($service->properties )) {
- foreach ($service->properties as $name => $value) {
- $rows[] = [' ' . $name, $value];
- }
- }
- }
- $io->table(['Services'], $rows);
- }
- }
}
diff --git a/src/Context/SiteContext.php b/src/Context/SiteContext.php
index 2a0aec1..156e8e3 100644
--- a/src/Context/SiteContext.php
+++ b/src/Context/SiteContext.php
@@ -2,6 +2,7 @@
namespace Aegir\Provision\Context;
+use Aegir\Provision\Application;
use Aegir\Provision\Context;
use Symfony\Component\Config\Definition\ConfigurationInterface;
@@ -19,6 +20,33 @@ class SiteContext extends Context implements ConfigurationInterface
*/
public $type = 'site';
+ /**
+ * PlatformContext constructor.
+ *
+ * @param $name
+ * @param $console_config
+ * @param Application $application
+ * @param array $options
+ */
+ function __construct($name, $console_config, Application $application, array $options = [])
+ {
+ parent::__construct($name, $console_config, $application, $options);
+
+ // Load "db_server" context.
+// if (isset($this->config['service_subscriptions']['db'])) {
+// $this->db_server = $application->getContext($this->config['service_subscriptions']['db']['server']);
+// }
+
+ $this->logger = $application->logger;
+
+ if (isset($this->config['platform'])) {
+ $this->platform = $application->getContext(
+ $this->config['platform']
+ );
+ }
+
+ }
+
static function option_documentation()
{
return [
@@ -35,6 +63,16 @@ class SiteContext extends Context implements ConfigurationInterface
];
}
+
+ public function verify() {
+ parent::verify();
+
+ // $this->db_server->service('db')->verify();
+// $this->platform->verify();
+
+// return "Site Context Verified: " . $this->name;
+ }
+
// /**
// * Write out this named context to an alias file.
// */
diff --git a/src/Service.php b/src/Service.php
index 29849bb..f780552 100644
--- a/src/Service.php
+++ b/src/Service.php
@@ -27,6 +27,14 @@ class Service {
function verify() {
$this->writeConfigurations();
}
+
+ /**
+ * List context types that are allowed to subscribe to this service.
+ * @return array
+ */
+ static function allowedContexts() {
+ return [];
+ }
/**
* Write this service's configurations.
@@ -35,9 +43,11 @@ class Service {
if (empty($this->getConfigurations()[$this->context->type])) {
return;
}
+ $this->context->application->logger->info('CONTEXT ' . $this->context->type);
foreach ($this->getConfigurations()[$this->context->type] as $configuration_class) {
$config = new $configuration_class($this->context, $this);
$config->write();
+ $this->context->application->logger->info('Wrote ' . $config->description . ' to ' . $config->filename());
}
}
@@ -63,6 +73,37 @@ class Service {
public function getName() {
return $this::SERVICE;
}
+
+ /**
+ * Return a list of user configurable options that this service provides to Server Context objects.
+ */
+ static function server_options() {
+ return [];
+// return [
+// 'http_port' => 'The port which the web service is running on.',
+// 'web_group' => 'server with http: OS group for permissions; working default will be attempted',
+// ];
+ }
+
+ /**
+ * Return a list of user configurable options that this service provides to Platform Context objects.
+ */
+ static function platform_options() {
+ return [];
+// return [
+// 'platform_extra_config' => 'Extra lines of configuration to add to this platform.',
+// ];
+ }
+
+ /**
+ * Return a list of user configurable options that this service provides to Site Context objects.
+ */
+ static function site_options() {
+ return [];
+// return [
+// 'site_mail' => 'The email address to use for the ServerAdmin configuration.',
+// ];
+ }
/**
* LEGACY
@@ -401,16 +442,6 @@ class Service {
// }
/**
- * Return service-specific configuration options for help.
- *
- * @return
- * array('option' => 'description')
- */
- static function option_documentation() {
- return array();
- }
-
- /**
* Save symlink for this server from /var/aegir/config/APPLICATION_NAME.conf -> /var/aegir/config/SERVER/APPLICATION_NAME.conf
*
* If service requires a fixed path config file, implement this function in the init_server() method.
diff --git a/src/Service/DbService.php b/src/Service/DbService.php
index 517ac87..8988e7a 100644
--- a/src/Service/DbService.php
+++ b/src/Service/DbService.php
@@ -24,13 +24,42 @@ class DbService extends Service
const SERVICE_NAME = 'Database Server';
- static function option_documentation()
+ /**
+ * Implements Service::server_options()
+ *
+ * @return array
+ */
+ static function server_options()
{
return [
'master_db' => 'server with db: Master database connection info, {type}://{user}:{password}@{host}',
'db_grant_all_hosts' => 'Grant access to site database users from any web host. If set to TRUE, any host will be allowed to connect to MySQL site databases on this server using the generated username and password. If set to FALSE, web hosts will be granted access by their detected IP address.',
];
}
+
+ /**
+ * List context types that are allowed to subscribe to this service.
+ * @return array
+ */
+ static function allowedContexts() {
+ return [
+ 'site'
+ ];
+ }
+
+ /**
+ * Implements Service::server_options()
+ *
+ * @return array
+ */
+ static function site_options()
+ {
+ return [
+ 'db_name' => 'The name of the database. Default: Automatically generated.',
+ 'db_user' => 'The username used to access the database. Default: Automatically generated.',
+ 'db_password' => 'The password used to access the database. Default: Automatically generated.',
+ ];
+ }
/**
* Register the db handler for sites, based on the db_server option.
diff --git a/src/Service/Http/Apache/Configuration/PlatformConfiguration.php b/src/Service/Http/Apache/Configuration/PlatformConfiguration.php
index 096fd06..3265de8 100644
--- a/src/Service/Http/Apache/Configuration/PlatformConfiguration.php
+++ b/src/Service/Http/Apache/Configuration/PlatformConfiguration.php
@@ -16,16 +16,10 @@ class PlatformConfiguration extends Configuration {
const SERVICE_TYPE = 'apache';
- public $template = 'server.tpl.php';
- public $description = 'web server configuration file';
+ public $template = 'platform.tpl.php';
+ public $description = 'platform configuration file';
function filename() {
- if (isset($this->data['application_name'])) {
- $file = $this->data['application_name'] . '.conf';
- return $this->data['server']->config_path . '/' . $file;
- }
- else {
- return FALSE;
- }
+ return $this->service->properties['http_platformd_path'] . '/' . ltrim($this->context->name, '@') . '.conf';
}
} \ No newline at end of file
diff --git a/src/Service/Http/Apache/Configuration/SiteConfiguration.php b/src/Service/Http/Apache/Configuration/SiteConfiguration.php
index 3ac18a6..f7c23f5 100644
--- a/src/Service/Http/Apache/Configuration/SiteConfiguration.php
+++ b/src/Service/Http/Apache/Configuration/SiteConfiguration.php
@@ -22,12 +22,18 @@ class SiteConfiguration extends Configuration {
function filename() {
- if (drush_get_option('provision_apache_conf_suffix', FALSE)) {
- return $this->data['http_vhostd_path'] . '/' . $this->uri . '.conf';
- }
- else {
- return $this->data['http_vhostd_path'] . '/' . $this->uri;
- }
+ $file = $this->uri . '.conf';
+
+// return $this->service->properties['http_platformd_path'] . '/' . ltrim($this->context->name, '@') . '.conf';
+ return $this->context->console_config['config_path'] . '/' . $this->context->name . '/' . $file;
+
+// return $this->context->config['config_path'];
+// if (drush_get_option('provision_apache_conf_suffix', FALSE)) {
+// return $this->data['http_vhostd_path'] . '/' . $this->uri . '.conf';
+// }
+// else {
+// return $this->data['http_vhostd_path'] . '/' . $this->uri;
+// }
}
function process() {
diff --git a/src/Service/HttpService.php b/src/Service/HttpService.php
index 79c00ce..af6ce49 100644
--- a/src/Service/HttpService.php
+++ b/src/Service/HttpService.php
@@ -24,16 +24,31 @@ class HttpService extends Service {
protected $ssl_enabled = FALSE;
- static function option_documentation() {
- return array(
+
+ /**
+ * Implements Service::server_options()
+ *
+ * @return array
+ */
+ static function server_options()
+ {
+ return [
'http_port' => 'The port which the web service is running on.',
-// 'http_platformd_path' => 'The path to store platforms.',
-// 'http_postd_path' => 'The path to store post configuration.',
'web_group' => 'server with http: OS group for permissions; working default will be attempted',
'web_disable_url' => 'server with http: URL disabled sites are redirected to; default {master_url}/hosting/disabled',
'web_maintenance_url' => 'server with http: URL maintenance sites are redirected to; default {master_url}/hosting/maintenance',
'restart_command' => 'The command to reload the web server configuration;'
- );
+ ];
+ }
+
+ /**
+ * List context types that are allowed to subscribe to this service.
+ * @return array
+ */
+ static function allowedContexts() {
+ return [
+ 'platform'
+ ];
}
/**
diff --git a/src/ServiceSubscription.php b/src/ServiceSubscription.php
new file mode 100644
index 0000000..bf20e29
--- /dev/null
+++ b/src/ServiceSubscription.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * A context's subscription to a service. Handles properties specific to a
+ * context for each service.
+ *
+ * @see Provision_Service
+ */
+
+namespace Aegir\Provision;
+
+class ServiceSubscription {
+
+ public $context;
+ public $service;
+ public $server;
+ public $type;
+
+ function __construct($context, $server, $service_name) {
+ $this->context = $context;
+ $this->server = $server;
+ $this->service = $server->getService($service_name);
+ $this->type = $server->getService($service_name)->type;
+ }
+}