Commit 66a1b847 authored by Steven Jones's avatar Steven Jones

Refactor the http service to use the autoloader.

parent 3a73e1a9
......@@ -178,7 +178,7 @@ class Provision_Context {
// Set up subscriptions for the available services.
$service_list = drush_command_invoke_all('provision_services');
foreach ($service_list as $service => $default) {
$class = "provisionService_{$service}";
$class = "Provision_Service_{$service}";
$func = "subscribe_{$this->type}";
if (method_exists($class, $func)) {
call_user_func(array($class, $func), $this);
......@@ -238,7 +238,7 @@ class Provision_Context {
* Override service owner with a context name as accepted by d().
*
* @return
* A provisionService object.
* A Provision_Service object.
*/
function service($service, $name = null) {
if (isset($this->service_subs[$service])) {
......@@ -256,7 +256,7 @@ class Provision_Context {
* Call method $callback on each of the context's service objects.
*
* @param $callback
* A provisionService method.
* A Provision_Service method.
* @return
* An array of return values from method implementations.
*/
......
......@@ -35,7 +35,7 @@ class Provision_Context_server extends Provision_Context {
if (preg_match('%^' . $base_dir . '/([a-z]+)/(?:\1)_service.inc$%', $service_file, $match)) {
$types[] = $match[1];
include_once($service_file);
$options = array_merge($options, call_user_func(array(sprintf('provisionService_%s_%s', $service, $match[1]), 'option_documentation')));
$options = array_merge($options, call_user_func(array(sprintf('Provision_Service_%s_%s', $service, $match[1]), 'option_documentation')));
}
}
$options['--' . $service . '_service_type'] = 'server: ' . implode(', ', $types) . ', or null; default ' . (empty($default) ? 'null' : $default);
......
......@@ -82,7 +82,7 @@ class Provision_Service_dns extends Provision_Service {
* need to be merged, but then the cluster_web_server parameter need to be
* renamed...
*
* @see provisionService_http_cluster::_each_server()
* @see Provision_Service_http_cluster::_each_server()
*/
function _each_server($method, $args = array()) {
// Return True by default.
......
<?php
/**
* Apache platform level configuration file class
*/
class ProvisionConfig_Apache_Platform extends Provision_Config_Http_Platform {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_dir_config', $this->data));
}
}
<?php
/**
* Apache server level configuration file class
*/
class Provision_Config_Apache_Server extends Provision_Config_Http_Server {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data));
}
}
<?php
/**
* Apache site level config class. Virtual host.
*/
class Provision_Config_Apache_Site extends Provision_Config_Http_Site {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_vhost_config', $this->uri, $this->data));
}
}
<?php
/**
* Server config file for Apache + SSL.
*
* This configuration file replaces the Apache server configuration file, but
* inside the template, the original file is once again included.
*
* This config is primarily reponsible for enabling the SSL relation settings,
* so that individual sites can just enable them.
*/
class Provision_Config_Apache_Ssl_Server extends Provision_Config_Http_Ssl_Server {
// We use the same extra_config as the apache_server config class.
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data));
}
}
<?php
/**
* Virtual host config file for Apache + SSL.
*
* This file is created in addition to the existing virtual host,
* and includes some extra directives.
*/
class Provision_Config_Apache_Ssl_Site extends Provision_Config_Http_Ssl_Site {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_vhost_config', $this->uri, $this->data));
}
}
<?php
/**
* Base class for HTTP config files.
*
* This class will publish the config files to remote
* servers automatically.
*/
class Provision_Config_Http extends Provision_Config {
function write() {
parent::write();
$this->data['server']->sync($this->filename());
}
function unlink() {
parent::unlink();
$this->data['server']->sync($this->filename());
}
}
<?php
/**
* Base class for platform configuration files.
*/
class Provision_Config_Http_Platform extends Provision_Config_Http {
public $template = 'platform.tpl.php';
public $description = 'platform configuration file';
function filename() {
return $this->data['http_platformd_path'] . '/' . ltrim($this->context->name, '@') . '.conf';
}
}
<?php
/**
* Base configuration class for server level http configs.
*
* This class uses the service defined application_name, to generate
* a top level $app_name.conf for the service.
*
* Each server has it's own configuration, and this class will
* automatically generate a symlink to the correct file for each
* server.
*/
class Provision_Config_Http_Server extends Provision_Config_Http {
public $template = 'server.tpl.php';
public $description = 'web server configuration file';
function write() {
parent::write();
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
// We link the app_name.conf file on the remote server to the right version.
$cmd = sprintf('ln -sf %s %s',
escapeshellarg($this->data['server']->config_path . '/' . $file),
escapeshellarg($this->data['server']->aegir_root . '/config/' . $file)
);
if ($this->data['server']->shell_exec($cmd)) {
drush_log(dt("Created symlink for %file on %server", array(
'%file' => $file,
'%server' => $this->data['server']->remote_host,
)));
};
}
}
function filename() {
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
return $this->data['server']->config_path . '/' . $file;
}
else {
return FALSE;
}
}
}
<?php
// $Id$
/**
* @file
* Configuration classes for the HTTP service.
*/
/**
* Base class for HTTP config files.
*
* This class will publish the config files to remote
* servers automatically.
*/
class provisionConfig_http extends Provision_Config {
function write() {
parent::write();
$this->data['server']->sync($this->filename());
}
function unlink() {
parent::unlink();
$this->data['server']->sync($this->filename());
}
}
/**
* Base configuration class for server level http configs.
*
* This class uses the service defined application_name, to generate
* a top level $app_name.conf for the service.
*
* Each server has it's own configuration, and this class will
* automatically generate a symlink to the correct file for each
* server.
*/
class provisionConfig_http_server extends provisionConfig_http {
public $template = 'server.tpl.php';
public $description = 'web server configuration file';
function write() {
parent::write();
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
// We link the app_name.conf file on the remote server to the right version.
$cmd = sprintf('ln -sf %s %s',
escapeshellarg($this->data['server']->config_path . '/' . $file),
escapeshellarg($this->data['server']->aegir_root . '/config/' . $file)
);
if ($this->data['server']->shell_exec($cmd)) {
drush_log(dt("Created symlink for %file on %server", array(
'%file' => $file,
'%server' => $this->data['server']->remote_host,
)));
};
}
}
function filename() {
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
return $this->data['server']->config_path . '/' . $file;
}
else {
return FALSE;
}
}
}
/**
* Base class for platform configuration files.
*/
class provisionConfig_http_platform extends provisionConfig_http {
public $template = 'platform.tpl.php';
public $description = 'platform configuration file';
function filename() {
return $this->data['http_platformd_path'] . '/' . ltrim($this->context->name, '@') . '.conf';
}
}
/**
* Base class for virtual host configuration files.
*/
class provisionConfig_http_site extends provisionConfig_http {
class Provision_Config_Http_Site extends Provision_Config_Http {
public $template = 'vhost.tpl.php';
// The template file to use when the site has been disabled.
public $disabled_template = 'vhost_disabled.tpl.php';
......
<?php
/**
* Base class for SSL enabled server level config.
*/
class Provision_Config_Http_Ssl_Server extends Provision_Config_Http_Server {
public $template = 'server_ssl.tpl.php';
public $description = 'encryption enabled webserver configuration';
}
<?php
/**
* Base class for SSL enabled virtual hosts.
*
* This class primarily abstracts the process of making sure the relevant keys
* are synched to the server when the config files that use them get created.
*/
class Provision_Config_Http_Ssl_Site extends Provision_Config_Http_Site {
public $template = 'vhost_ssl.tpl.php';
public $disabled_template = 'vhost_ssl_disabled.tpl.php';
public $description = 'encrypted virtual host configuration';
function write() {
parent::write();
$ip_addresses = drush_get_option('site_ip_addresses', array(), 'site');
if ($this->ssl_enabled && $this->ssl_key) {
$path = dirname($this->data['ssl_cert']);
// Make sure the ssl.d directory in the server ssl.d exists.
provision_file()->create_dir($path,
dt("SSL Certificate directory for %key on %server", array(
'%key' => $this->ssl_key,
'%server' => $this->data['server']->remote_host,
)), 0700);
// Touch a file in the server's copy of this key, so that it knows the key is in use.
touch("{$path}/{$this->uri}.receipt");
// Copy the certificates to the server's ssl.d directory.
provision_file()->copy(
$this->data['ssl_cert_source'],
$this->data['ssl_cert']);
provision_file()->copy(
$this->data['ssl_cert_key_source'],
$this->data['ssl_cert_key']);
// Copy the chain certificate, if it is set.
if (!empty($this->data['ssl_chain_cert_source'])) {
provision_file()->copy(
$this->data['ssl_chain_cert_source'],
$this->data['ssl_chain_cert']);
}
// Sync the key directory to the remote server.
$this->data['server']->sync($path, array(
'exclude' => "{$path}/*.receipt", // Don't need to synch the receipts
));
}
elseif ($ip = $ip_addresses[$this->data['server']->name]) {
if ($ssl_key = Provision_Service_http_ssl::get_ip_certificate($ip, $this->data['server'])) {
$this->clear_certs($ssl_key);
}
}
}
/**
* Remove a stale certificate file from the server.
*/
function unlink() {
parent::unlink();
$ip_addresses = drush_get_option('site_ip_addresses', array(), 'site');
if ($this->ssl_enabled && $this->ssl_key) {
$this->clear_certs($this->ssl_key);
}
elseif ($ip = $ip_addresses[$this->data['server']->name]) {
if ($ssl_key = Provision_Service_http_ssl::get_ip_certificate($ip, $this->data['server'])) {
$this->clear_certs($ssl_key);
}
}
}
/**
* Small utility function to stop code duplication.
*/
private function clear_certs($ssl_key) {
$path = $this->data['server']->http_ssld_path . "/$ssl_key";
// Remove the file system reciept we left for this file
provision_file()->unlink("{$path}/{$this->uri}.receipt")->
succeed(dt("Deleted SSL Certificate association stub for %site on %server", array(
'%site' => $this->uri,
'%server' => $this->data['server']->remote_host)));
$used = Provision_Service_http_ssl::certificate_in_use($ssl_key, $this->data['server']);
if (!$used) {
// we can remove the certificate from the server ssl.d directory.
_provision_recursive_delete($path);
// remove the file from the remote server too.
$this->data['server']->sync($path);
// Most importantly, we remove the hold this cert had on the IP address.
Provision_Service_http_ssl::free_certificate_ip($ssl_key, $this->data['server']);
}
}
}
<?php
/**
* Nginx server level configuration file class
*/
class Provision_Config_Nginx_Server extends Provision_Config_Http_Server {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_nginx_server_config', $this->data));
}
}
<?php
/**
* Nginx site level config class. Virtual host.
*/
class Provision_Config_Nginx_Site extends Provision_Config_Http_Site {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_nginx_vhost_config', $this->uri, $this->data));
}
}
<?php
/**
* Server config file for Nginx + SSL.
*
* This configuration file replaces the Nginx server configuration file, but
* inside the template, the original file is once again included.
*
* This config is primarily reponsible for enabling the SSL relation settings,
* so that individual sites can just enable them.
*/
class Provision_Config_Nginx_Ssl_Server extends Provision_Config_Http_Ssl_Server {
// We use the same extra_config as the nginx_server config class.
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_nginx_server_config', $this->data));
}
}
<?php
/**
* Virtual host config file for Nginx + SSL.
*
* This file is created in addition to the existing virtual host,
* and includes some extra directives.
*/
class Provision_Config_Nginx_Ssl_Site extends Provision_Config_Http_Ssl_Site {
function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_nginx_vhost_config', $this->uri, $this->data));
}
}
<?php
// Base http service class.
class Provision_Service_http extends Provision_Service {
public $service = 'http';
protected $ssl_enabled = FALSE;
/**
* Support the ability to cloak the database credentials using environment variables.
*/
function cloaked_db_creds() {
return FALSE;
}
function verify_server_cmd() {
$this->create_config($this->context->type);
$this->parse_configs();
}
function verify_platform_cmd() {
$this->create_config($this->context->type);
$this->parse_configs();
}
function verify_site_cmd() {
$this->create_config($this->context->type);
$this->parse_configs();
}
/**
* Register the http handler for platforms, based on the web_server option.
*/
static function subscribe_platform($context) {
$context->setProperty('web_server', '@server_master');
$context->is_oid('web_server');
$context->service_subscribe('http', $context->web_server->name);
}
}
<?php
class Provision_Service_http_apache extends Provision_Service_http_public {
protected $application_name = 'apache';
protected $has_restart_cmd = TRUE;
function default_restart_cmd() {
return Provision_Service_http_apache::apache_restart_cmd();
}
function cloaked_db_creds() {
return TRUE;
}
function init_server() {
parent::init_server();
$this->configs['server'][] = 'Provision_Config_Apache_Server';
$this->configs['platform'][] = 'ProvisionConfig_Apache_Platform';
$this->configs['site'][] = 'Provision_Config_Apache_Site';
}
/**
* Guess at the likely value of the http_restart_cmd.
*
* This method is a static so that it can be re-used by the apache_ssl
* service, even though it does not inherit this class.
*/
public static function apache_restart_cmd() {
$command = '/usr/sbin/apachectl'; // A proper default for most of the world
foreach (explode(':', $_SERVER['PATH']) as $path) {
$options[] = "$path/apache2ctl";
$options[] = "$path/apachectl";
}
// Try to detect the apache restart command.
$options[] = '/usr/local/sbin/apachectl'; // freebsd
$options[] = '/usr/sbin/apache2ctl'; // debian + apache2
$options[] = '/usr/apache2/2.2/bin'; // Solaris
$options[] = $command;
foreach ($options as $test) {
if (is_executable($test)) {
$command = $test;
break;
}
}
return "sudo $command graceful";
}
/**
* Restart apache to pick up the new config files.
*/
function parse_configs() {
return $this->restart();
}
}
<?php
/**
* Apache SSL service class.
*
* This class doesn't extend the apache service itself, so there may
* be some duplication of code between them. The majority of the
* functionality is however implemented in the Provision_Service_http_public
* class, which we do extend.
*/
class Provision_Service_http_apache_ssl extends Provision_Service_http_ssl {
// We share the application name with apache.
protected $application_name = 'apache';
protected $has_restart_cmd = TRUE;
function default_restart_cmd() {
// The apache service defines it's restart command as a static
// method so that we can make use of it here.
return Provision_Service_http_apache::apache_restart_cmd();
}
public $ssl_enabled = TRUE;
function cloaked_db_creds() {
return TRUE;
}
/**
* Initialize the configuration files.
*
* These config classes are a mix of the SSL and Non-SSL apache
* classes. In some cases they extend the Apache classes too.
*/
function init_server() {
parent::init_server();
// Replace the server config with our own. See the class for more info.
$this->configs['server'][] = 'Provision_Config_Apache_Ssl_Server';
// Just re-use the standard platform config.
$this->configs['platform'][] = 'ProvisionConfig_Apache_Platform';
$this->configs['site'][] = 'Provision_Config_Apache_Ssl_Site';
}
/**
* Restart apache to pick up the new config files.
*/
function parse_configs() {
return $this->restart();
}
}
<?php
class provisionService_http_cluster extends provisionService_http {
class Provision_Service_http_cluster extends Provision_Service_http {
static function option_documentation() {
return array(
'--cluster_web_servers' => 'server with cluster: comma-separated list of web servers.'
......
<?php
class Provision_Service_http_nginx extends Provision_Service_http_public {
protected $application_name = 'nginx';
protected $has_restart_cmd = TRUE;
function default_restart_cmd() {
return Provision_Service_http_nginx::nginx_restart_cmd();
}
function init_server() {
parent::init_server();
$this->configs['server'][] = 'Provision_Config_Nginx_Server';
$this->configs['site'][] = 'Provision_Config_Nginx_Site';
$this->server->setProperty('nginx_has_gzip', 0);
$this->server->setProperty('nginx_has_new_version', 0);
$this->server->setProperty('nginx_web_server', 0);
$this->server->setProperty('nginx_has_upload_progress', 0);
}
function save_server() {
// Check if some nginx features are supported and save them for later.
$this->server->shell_exec('nginx -V');
$this->server->nginx_has_gzip = preg_match("/(with-http_gzip_static_module)/", implode('', drush_shell_exec_output()), $match);
$this->server->nginx_has_upload_progress = preg_match("/(nginx-upload-progress-module)/", implode('', drush_shell_exec_output()), $match);
$this->server->nginx_has_new_version = preg_match("/(Barracuda\/0\.9\.)/", implode('', drush_shell_exec_output()), $match);
$this->server->provision_db_cloaking = FALSE;
$this->server->nginx_web_server = 1;
}
function verify_server_cmd() {
provision_file()->copy(dirname(__FILE__) . '/nginx_advanced_include.conf', $this->server->include_path . '/nginx_advanced_include.conf');
$this->sync($this->server->include_path . '/nginx_advanced_include.conf');
provision_file()->copy(dirname(__FILE__) . '/nginx_simple_include.conf', $this->server->include_path . '/nginx_simple_include.conf');
$this->sync($this->server->include_path . '/nginx_simple_include.conf');
provision_file()->copy(dirname(__FILE__) . '/fastcgi_params.conf', $this->server->include_path . '/fastcgi_params.conf');