Merge branch 'feature/generate-webserver-config-6120'

resolves #6120
This commit is contained in:
Eric Lippmann 2014-11-13 15:10:12 +01:00
commit 86a9c7f8c6
5 changed files with 346 additions and 0 deletions

View File

@ -4,7 +4,10 @@
namespace Icinga\Module\Setup\Clicommands; namespace Icinga\Module\Setup\Clicommands;
use Icinga\Application\Logger;
use Icinga\Cli\Command; use Icinga\Cli\Command;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Setup\Webserver;
class ConfigCommand extends Command class ConfigCommand extends Command
{ {
@ -60,4 +63,79 @@ class ConfigCommand extends Command
printf($this->translate("Successfully created configuration directory at: %s\n"), $path); printf($this->translate("Successfully created configuration directory at: %s\n"), $path);
} }
/**
* Create webserver configuration
*
* USAGE:
*
* icingacli setup config webserver <apache|nginx> [options]
*
* OPTIONS:
*
* --path=<urlpath> The URL path to Icinga Web 2 [/icingaweb]
*
* --root/--document-root=<directory> The directory from which the webserver will serve files [./public]
*
* --config=<directory> Path to Icinga Web 2's configuration files [/etc/icingaweb]
*
* --file=<filename> Write configuration to file [stdout]
*
*
* EXAMPLES:
*
* icingacli setup config webserver apache
*
* icingacli setup config webserver apache --path /icingaweb --document-root /usr/share/icingaweb/public --config=/etc/icingaweb
*
* icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb.conf
*
* icingacli setup config webserver nginx
*/
public function webserverAction()
{
if (($type = $this->params->getStandalone()) === null) {
$this->fail($this->translate('Argument type is mandatory.'));
}
try {
$webserver = Webserver::createInstance($type);
} catch (ProgrammingError $e) {
$this->fail($this->translate('Unknown type') . ': ' . $type);
}
$urlPath = $this->params->get('path', $webserver->getUrlPath());
if (! is_string($urlPath) || strlen(trim($urlPath)) === 0) {
$this->fail($this->translate('The argument --path expects a URL path'));
}
$documentRoot = $this->params->get('root', $this->params->get('document-root', $webserver->getDocumentRoot()));
if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) {
$this->fail($this->translate(
'The argument --root/--document-root expects a directory from which the webserver will serve files'
));
}
$configDir = $this->params->get('config', $webserver->getConfigDir());
if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) {
$this->fail($this->translate(
'The argument --config expects a path to Icinga Web 2\'s configuration files'
));
}
$webserver
->setDocumentRoot($documentRoot)
->setConfigDir($configDir)
->setUrlPath($urlPath);
$config = $webserver->generate() . "\n";
if (($file = $this->params->get('file')) !== null) {
if (file_exists($file) === true) {
$this->fail(sprintf($this->translate('File %s already exists. Please delete it first.'), $file));
}
Logger::info($this->translate('Write %s configuration to file: %s'), $type, $file);
$re = file_put_contents($file, $config);
if ($re === false) {
$this->fail($this->translate('Could not write to file') . ': ' . $file);
}
Logger::info($this->translate('Successfully written %d bytes to file'), $re);
return true;
}
echo $config;
return true;
}
} }

View File

@ -0,0 +1,168 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Setup;
use Icinga\Application\Icinga;
use Icinga\Exception\ProgrammingError;
/**
* Base class for generating webserver configuration
*/
abstract class Webserver
{
/**
* Document root
*
* @var string
*/
protected $documentRoot;
/**
* URL path of Icinga Web 2
*
* @var string
*/
protected $urlPath = '/icingaweb';
/**
* Path to Icinga Web 2's configuration files
*
* @var string
*/
protected $configDir;
/**
* Create instance by type name
*
* @param string $type
*
* @return WebServer
*
* @throws ProgrammingError
*/
public static function createInstance($type)
{
$class = __NAMESPACE__ . '\\Webserver\\' . ucfirst($type);
if (class_exists($class)) {
return new $class();
}
throw new ProgrammingError('Class "%s" does not exist', $class);
}
/**
* Generate configuration
*
* @return string
*/
public function generate()
{
$template = $this->getTemplate();
$searchTokens = array(
'{urlPath}',
'{documentRoot}',
'{configDir}',
);
$replaceTokens = array(
$this->getUrlPath(),
$this->getDocumentRoot(),
$this->getConfigDir()
);
$template = str_replace($searchTokens, $replaceTokens, $template);
return $template;
}
/**
* Specific template
*
* @return string
*/
abstract protected function getTemplate();
/**
* Set the URL path of Icinga Web 2
*
* @param string $urlPath
*
* @return $this
*/
public function setUrlPath($urlPath)
{
$this->urlPath = '/' . ltrim(trim((string) $urlPath), '/');
return $this;
}
/**
* Get the URL path of Icinga Web 2
*
* @return string
*/
public function getUrlPath()
{
return $this->urlPath;
}
/**
* Set the document root
*
* @param string $documentRoot
*
* @return $this
*/
public function setDocumentRoot($documentRoot)
{
$this->documentRoot = trim((string) $documentRoot);
return $this;
}
/**
* Detect the document root
*
* @return string
*/
public function detectDocumentRoot()
{
return Icinga::app()->getBaseDir('public');
}
/**
* Get the document root
*
* @return string
*/
public function getDocumentRoot()
{
if ($this->documentRoot === null) {
$this->documentRoot = $this->detectDocumentRoot();
}
return $this->documentRoot;
}
/**
* Set the configuration directory
*
* @param string $configDir
*
* @return $this
*/
public function setConfigDir($configDir)
{
$this->configDir = (string) $configDir;
return $this;
}
/**
* Get the configuration directory
*
* @return string
*/
public function getConfigDir()
{
if ($this->configDir === null) {
return Icinga::app()->getConfigDir();
}
return $this->configDir;
}
}

View File

@ -0,0 +1,61 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Setup\Webserver;
use Icinga\Module\Setup\Webserver;
/**
* Generate Apache 2.x configuration
*/
class Apache extends Webserver
{
/**
* @return array
*/
protected function getTemplate()
{
return <<<'EOD'
Alias {urlPath} "{documentRoot}"
<Directory "{documentRoot}">
Options SymLinksIfOwnerMatch
AllowOverride None
<IfModule mod_authz_core.c>
# Apache 2.4
<RequireAll>
Require all granted
</RequireAll>
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order allow,deny
Allow from all
</IfModule>
SetEnv ICINGAWEB_CONFIGDIR "{configDir}"
EnableSendfile Off
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase {urlPath}/
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</IfModule>
<IfModule !mod_rewrite.c>
DirectoryIndex error_norewrite.html
ErrorDocument 404 /error_norewrite.html
</IfModule>
</Directory>
EOD;
}
}

View File

@ -0,0 +1,38 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Setup\Webserver;
use Icinga\Module\Setup\Webserver;
/**
* Generate nginx configuration
*/
class Nginx extends Webserver
{
/**
* Specific template
*
* @return array|string
*/
protected function getTemplate()
{
return <<<'EOD'
location ~ ^{urlPath}/index\.php(.*)$ {
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME {documentRoot}/index.php;
fastcgi_param ICINGAWEB_CONFIGDIR {configDir};
}
location ~ ^{urlPath}(.+)? {
alias {documentRoot};
index index.php;
try_files $1 $uri $uri/ {urlPath}/index.php$is_args$args;
}
EOD;
}
}

View File

@ -0,0 +1 @@
<h1>The rewrite module is not enabled</h1>