Skip to content
Commits on Source (23)
......@@ -54,7 +54,7 @@ if ($debug){
}
try {
$application = new Application();
$application = new Application($input, $output);
$application->run();
}
catch (\Exception $e) {
......
......@@ -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;
}
}
......@@ -3,6 +3,7 @@
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;
......@@ -70,7 +71,6 @@ abstract class Command extends BaseCommand
// Load context from context_name argument.
$this->context_name = $this->input->getArgument('context_name');
$this->context = $this->getApplication()->getContext($this->context_name);
$this->context->logger = new ConsoleLogger($output);
}
catch (\Exception $e) {
......
......@@ -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);
}
......
......@@ -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.
......
......@@ -6,6 +6,8 @@
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;
......@@ -49,6 +51,17 @@ class Context
* init(), set defaults with setProperty().
*/
protected $properties = [];
/**
* @var array
* A list of services associated with this context.
*/
protected $services = [];
/**
* @var \Aegir\Provision\Application;
*/
public $application;
/**
* @var LoggerInterface
......@@ -62,10 +75,12 @@ class Context
* @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();
}
/**
......@@ -105,13 +120,142 @@ 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')
......@@ -119,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
......@@ -136,6 +302,77 @@ class Context
return $tree_builder;
}
/**
* 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.
*
......@@ -200,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();
}
}
}
......@@ -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();
// }
}
......@@ -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);
}
}
}
......@@ -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.
// */
......
......@@ -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,10 +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->logger->notice('Wrote ' . $config->description . ' to ' . $config->filename());
$this->context->application->logger->info('Wrote ' . $config->description . ' to ' . $config->filename());
}
}
......@@ -64,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 +441,6 @@ class Service {
// return TRUE;
// }
/**
* 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
*
......
......@@ -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.
......
......@@ -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
......@@ -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() {
......@@ -48,6 +54,17 @@ class SiteConfiguration extends Configuration {
if (!$this->site_enabled) {
$this->template = $this->disabled_template;
}
$app_dir = $this->context->console_config['config_path'] . '/' . $this->service->getType();
// $this->data['http_port'] = $this->service->properties['http_port'];
// $this->data['include_statement'] = '# INCLUDE STATEMENT';
// $this->data['http_pred_path'] = "{$app_dir}/pre.d";
// $this->data['http_postd_path'] = "{$app_dir}/post.d";
// $this->data['http_platformd_path'] = "{$app_dir}/platform.d";
// $this->data['extra_config'] = "";
$this->data['http_vhostd_path'] = "{$app_dir}/vhost.d";
}
}
\ No newline at end of file
<VirtualHost *:<?php print $http_port; ?>>
<?php if ($this->site_mail) : ?>
ServerAdmin <?php print $this->site_mail; ?>
<?php endif;?>
<?php
$aegir_root = drush_get_option('aegir_root');
if (!$aegir_root && $server->aegir_root) {
$aegir_root = $server->aegir_root;
}
?>
DocumentRoot <?php print $this->root; ?>
ServerName <?php print $this->uri; ?>
SetEnv db_type <?php print urlencode($db_type); ?>
SetEnv db_name <?php print urlencode($db_name); ?>
SetEnv db_user <?php print urlencode($db_user); ?>
SetEnv db_passwd <?php print urlencode($db_passwd); ?>
SetEnv db_host <?php print urlencode($db_host); ?>
SetEnv db_port <?php print urlencode($db_port); ?>
<?php
if (sizeof($this->aliases)) {
foreach ($this->aliases as $alias) {
print " ServerAlias " . $alias . "\n";
}
}
?>
<IfModule mod_rewrite.c>
RewriteEngine on
<?php
if ($this->redirection || $ssl_redirection) {
if ($ssl_redirection && !$this->redirection) {
print " # Redirect aliases in non-ssl to the same alias on ssl.\n";
print " RewriteRule ^/*(.*)$ https://%{HTTP_HOST}/$1 [NE,L,R=301]\n";
}
elseif ($ssl_redirection && $this->redirection) {
print " # Redirect all aliases + main uri to the main https uri.\n";
print " RewriteRule ^/*(.*)$ https://{$this->uri}/$1 [NE,L,R=301]\n";
}
elseif (!$ssl_redirection && $this->redirection) {
print " # Redirect all aliases to the main http url.\n";
print " RewriteCond %{HTTP_HOST} !^{$this->redirection}$ [NC]\n";
print " RewriteRule ^/*(.*)$ http://{$this->redirection}/$1 [NE,L,R=301]\n";
}
}
?>
RewriteRule ^/files/(.*)$ /sites/<?php print $this->uri; ?>/files/$1 [L]
RewriteCond <?php print $this->site_path; ?>/files/robots.txt -f
RewriteRule ^/robots.txt /sites/<?php print $this->uri; ?>/files/robots.txt [L]
</IfModule>
<?php print $extra_config; ?>
# Error handler for Drupal > 4.6.7
<Directory ~ "sites/.*/files">
<Files *>
SetHandler This_is_a_Drupal_security_line_do_not_remove
</Files>
Options None
Options +FollowSymLinks
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>
</Directory>
# Prevent direct reading of files in the private dir.
# This is for Drupal7 compatibility, which would normally drop
# a .htaccess in those directories, but we explicitly ignore those
<Directory "<?php print $this->site_path; ?>/private/" >
<Files *>
SetHandler This_is_a_Drupal_security_line_do_not_remove
</Files>
Deny from all
Options None
Options +FollowSymLinks
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>
</Directory>
<?php
$if_subsite = $this->data['http_subdird_path'] . '/' . $this->uri;
if (provision_hosting_feature_enabled('subdirs') && provision_file()->exists($if_subsite)->status()) {
print " Include " . $if_subsite . "/*.conf\n";
}
?>
</VirtualHost>
......@@ -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'
];
}
/**
......
<?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;
}
}