Skip to content
Commits on Source (31)
......@@ -54,7 +54,7 @@ if ($debug){
}
try {
$application = new Application();
$application = new Application($input, $output);
$application->run();
}
catch (\Exception $e) {
......
......@@ -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",
......
......@@ -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,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;
/**
......
......@@ -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.
......
......@@ -125,10 +125,15 @@ class Configuration {
* This is a stub to be implemented by subclasses.
*/
function process() {
if (is_object($this->store)) {
$this->data['records'] = array_filter(array_merge($this->store->loaded_records, $this->store->records));
}
return TRUE;
if (!empty($this->context->getProperties())) {
$this->data = $this->context->getProperties();
}
// @TODO: Remove legacy code.
// if (is_object($this->store)) {
// $this->data['records'] = array_filter(array_merge($this->store->loaded_records, $this->store->records));
// }
// return TRUE;
}
/**
......
......@@ -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;
......@@ -49,6 +52,22 @@ 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.
*
......@@ -56,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();
}
/**
......@@ -99,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')
......@@ -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
......@@ -130,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.
*
......@@ -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();
}
}
}
......@@ -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,14 +27,27 @@ 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.
*/
protected function writeConfigurations() {
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());
}
}
......@@ -60,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
......@@ -397,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
*
......
This diff is collapsed.
......@@ -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
......@@ -3,6 +3,10 @@
* @file Server.php
*
* Apache Configuration for Server Context.
*
* This class represents the file at /var/aegir/config/apache.conf.
*
*
* @see \Provision_Config_Apache_Server
* @see \Provision_Config_Http_Server
* @see \Provision_Config_Http_Server
......@@ -22,7 +26,7 @@ class ServerConfiguration extends Configuration {
function filename() {
if ($this->service->getType()) {
$file = $this->service->getType() . '.conf';
return $this->context->console_config['config_path'] . '/' . $file;
return $this->context->console_config['config_path'] . '/' . $this->context->name . '/' . $file;
}
else {
return FALSE;
......@@ -30,16 +34,14 @@ class ServerConfiguration extends Configuration {
}
function process()
{
$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['http_vhostd_path'] = "{$app_dir}/vhost.d";
$this->data['extra_config'] = "";
return parent::process();
parent::process();
$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['http_vhostd_path'] = "{$app_dir}/vhost.d";
$this->data['extra_config'] = "";
}
}
\ 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,17 +24,32 @@ 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'
];
}
/**
* Support the ability to cloak the database credentials using environment variables.
......
<?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;
}
}