Merge branch 'master' of ssh://git.icinga.org/icinga2-web into feature/host-overview--4179

This commit is contained in:
Jannis Moßhammer 2013-07-12 16:02:00 +02:00
commit 820ed8f7a8
26 changed files with 314 additions and 238 deletions

4
Vagrantfile vendored
View File

@ -48,6 +48,8 @@ Vagrant::Config.run do |config|
# an identifier, the second is the path on the guest to mount the # an identifier, the second is the path on the guest to mount the
# folder, and the third is the path on the host to the actual folder. # folder, and the third is the path on the host to the actual folder.
# # config.vm.share_folder "v-icinga2-web-pub", "/var/www/html/icinga2-web", "./pub" # # config.vm.share_folder "v-icinga2-web-pub", "/var/www/html/icinga2-web", "./pub"
config.vm.share_folder "v-test", "/vagrant/config", "./config", :owner => 'vagrant', :group => 'apache', :extra => 'dmode=775,fmode=775'
config.vm.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-test", "1"]
# Enable provisioning with Puppet stand alone. Puppet manifests # Enable provisioning with Puppet stand alone. Puppet manifests
# are contained in a directory path relative to this Vagrantfile. # are contained in a directory path relative to this Vagrantfile.
@ -56,7 +58,7 @@ Vagrant::Config.run do |config|
config.vm.provision :puppet do |puppet| config.vm.provision :puppet do |puppet|
puppet.module_path = ".vagrant-puppet/modules" puppet.module_path = ".vagrant-puppet/modules"
puppet.manifests_path = ".vagrant-puppet/manifests" puppet.manifests_path = ".vagrant-puppet/manifests"
#puppet.options = "-v -d" # # puppet.options = "-v -d"
end end
# The npm module jquery won't install via puppet because of an mysterious error # The npm module jquery won't install via puppet because of an mysterious error

View File

@ -66,8 +66,7 @@ class ModulesController extends ActionController
$this->manager->enableModule($this->_getParam('name')); $this->manager->enableModule($this->_getParam('name'));
$this->manager->loadModule($this->_getParam('name')); $this->manager->loadModule($this->_getParam('name'));
$this->getResponse()->setHeader('X-Icinga-Enable-Module', $this->_getParam('name')); $this->getResponse()->setHeader('X-Icinga-Enable-Module', $this->_getParam('name'));
$this->replaceLayout = true; $this->redirectNow('index?_render=body');
$this->indexAction();
} }

View File

@ -3,7 +3,7 @@
$url = Zend_Controller_Front::getInstance()->getRequest()->getRequestUri(); $url = Zend_Controller_Front::getInstance()->getRequest()->getRequestUri();
$currentKey = isset($this->navkey) ? $this->navkey : $url; $currentKey = isset($this->navkey) ? $this->navkey : $url;
$item = $this->navigation->listAll("menu"); $item = $this->navigation->keys("menu");
?> ?>
<?php if ($this->auth()->isAuthenticated()): ?> <?php if ($this->auth()->isAuthenticated()): ?>
<ul class="nav nav-tabs icinga-navigation" > <ul class="nav nav-tabs icinga-navigation" >

View File

@ -2,8 +2,8 @@
[localdb] [localdb]
type = ido type = ido
host = localhost host = localhost
user = "icinga" user = "icinga-idoutils"
pass = "icinga" pass = "***"
db = "icinga" db = "icinga"

24
doc/CONFIG.md Normal file
View File

@ -0,0 +1,24 @@
# Application and Module Configuration
The \Icinga\Application\Config class is a general purpose service to help you find, load and save
configuration data. It is used both by the Icinga 2 Web modules and the framework itself. With
INI files as source it enables you to store configuration in a familiar format. Icinga 2 Web
defines some configuration files for its own purposes. Please note that both modules and framework
keep their main configuration in the INI file called config.ini. Here's some example code:
<?php
use \Icinga\Application\Config as IcingaConfig;
// Retrieve the default timezone using 'Europe/Berlin' in case it is not set
IcingaConfig::app()->global->get('defaultTimezone', 'Europe/Berlin');
// If you don't pass a configuration name to IcingaConfig::app it tries to load values from the
// application's config.ini. For using other files you have to pass this parameter though.
// The following example loads a section from the application's authentication.ini:
IcingaConfig::app('authentication')->get('ldap-authentication');
// If you don't pass a configuration name to IcingaConfig::module it tries to load values from
// the module's config.ini. For using other files you have to pass this parameter though.
// The following example loads values from the example module's extra.ini:
IcingaConfig::module('example', 'extra')->logging->get('enabled', true);

View File

@ -44,7 +44,7 @@ abstract class ApplicationBootstrap
protected $loader; protected $loader;
protected $libdir; protected $libdir;
protected $config; protected $config;
protected $configFile; protected $configDir;
protected $appdir; protected $appdir;
protected $moduleManager; protected $moduleManager;
protected $isCli = false; protected $isCli = false;
@ -57,7 +57,7 @@ abstract class ApplicationBootstrap
* *
* @return void * @return void
*/ */
protected function __construct($configFile = null) protected function __construct($configDir)
{ {
$this->checkPrerequisites(); $this->checkPrerequisites();
$this->libdir = realpath(dirname(dirname(dirname(__FILE__)))); $this->libdir = realpath(dirname(dirname(dirname(__FILE__))));
@ -88,10 +88,7 @@ abstract class ApplicationBootstrap
) )
); );
if ($configFile === null) { $this->configDir = $configDir;
$configFile = dirname($this->libdir) . '/config/icinga.ini';
}
$this->configFile = $configFile;
require_once dirname(__FILE__) . '/functions.php'; require_once dirname(__FILE__) . '/functions.php';
} }
@ -100,7 +97,7 @@ abstract class ApplicationBootstrap
public function moduleManager() public function moduleManager()
{ {
if ($this->moduleManager === null) { if ($this->moduleManager === null) {
$this->moduleManager = new ModuleManager($this, $this->config->global->moduleFolder); $this->moduleManager = new ModuleManager($this, $this->configDir . '/enabledModules');
} }
return $this->moduleManager; return $this->moduleManager;
} }
@ -155,10 +152,10 @@ abstract class ApplicationBootstrap
return $this->config; return $this->config;
} }
public static function start($config = null) public static function start($configDir)
{ {
$class = get_called_class(); $class = get_called_class();
$obj = new $class(); $obj = new $class($configDir);
$obj->bootstrap(); $obj->bootstrap();
return $obj; return $obj;
} }
@ -217,11 +214,8 @@ abstract class ApplicationBootstrap
*/ */
protected function loadConfig() protected function loadConfig()
{ {
// TODO: add an absolutely failsafe config loader Config::$configDir = $this->configDir;
if (! @is_readable($this->configFile)) { $this->config = Config::app();
throw new \Exception('Cannot read config file: ' . $this->configFile);
}
$this->config = Config::getInstance($this->configFile);
return $this; return $this;
} }
@ -247,7 +241,7 @@ abstract class ApplicationBootstrap
*/ */
protected function configureErrorHandling() protected function configureErrorHandling()
{ {
if ($this->config->global->environment == 'development') { if ($this->config->get('global', 'environment') == 'development') {
error_reporting(E_ALL | E_NOTICE); error_reporting(E_ALL | E_NOTICE);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
ini_set('display_errors', 1); ini_set('display_errors', 1);
@ -264,7 +258,7 @@ abstract class ApplicationBootstrap
protected function setTimezone() protected function setTimezone()
{ {
date_default_timezone_set( date_default_timezone_set(
$this->config->{'global'}->get('timezone', 'UTC') $this->config->global->get('timezone', 'UTC')
); );
return $this; return $this;
} }

View File

@ -1,79 +1,115 @@
<?php <?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Application; namespace Icinga\Application;
use Icinga\Application\Modules\Module; use Icinga\Protocol\Ldap\Exception;
use Zend_Config_Ini; use Zend_Config_Ini;
use Zend_Config;
/**
* Global registry of application and module configuration.
*/
class Config extends Zend_Config_Ini class Config extends Zend_Config_Ini
{ {
protected $data; /**
protected static $instance; * Configuration directory where ALL (application and module) configuration is located
protected $configDir; * @var string
*/
public static $configDir;
public function listAll($what) /**
* The INI file this configuration has been loaded from
* @var string
*/
protected $configFile;
/**
* Application config instances per file
* @var array
*/
protected static $app = array();
/**
* Module config instances per file
* @var array
*/
protected static $modules = array();
/**
* Load configuration from the config file $filename
*
* @see Zend_Config_Ini::__construct
*
* @param string $filename
* @throws Exception
*/
public function __construct($filename)
{ {
if ($this->$what === null) { if (!@is_readable($filename)) {
throw new Exception('Cannot read config file: ' . $filename);
};
$this->configFile = $filename;
$section = null;
$options = array(
'allowModifications' => true
);
parent::__construct($filename, $section, $options);
}
/**
* Retrieve a application config instance
*
* @param string $configname
* @return mixed
*/
public static function app($configname = 'config')
{
if (!isset(self::$app[$configname])) {
$filename = self::$configDir . '/' . $configname . '.ini';
self::$app[$configname] = new Config(realpath($filename));
}
return self::$app[$configname];
}
/**
* Retrieve a module config instance
*
* @param string $modulename
* @param string $configname
* @return Config
*/
public static function module($modulename, $configname = 'config')
{
if (!isset(self::$modules[$modulename])) {
self::$modules[$modulename] = array();
}
$moduleConfigs = self::$modules[$modulename];
if (!isset($moduleConfigs[$configname])) {
$filename = self::$configDir . '/modules/' . $modulename . '/' . $configname . '.ini';
if (file_exists($filename)) {
$moduleConfigs[$configname] = new Config(realpath($filename));
} else {
$moduleConfigs[$configname] = null;
}
}
return $moduleConfigs[$configname];
}
/**
* Retrieve names of accessible sections or properties
*
* @param $name
* @return array
*/
public function keys($name = null)
{
if ($name === null) {
return array_keys($this->toArray());
} elseif ($this->$name === null) {
return array(); return array();
} else { } else {
return array_keys($this->$what->toArray()); return array_keys($this->$name->toArray());
} }
} }
public function getConfigDir()
{
return $this->configDir;
}
public function __construct($filename, $section = null, $options = false)
{
$options['allowModifications'] = true;
$this->configDir = dirname($filename);
return parent::__construct($filename, $section, $options);
}
public static function module($name, $file = null)
{
if ($file === null) {
$file = $name . '.ini'; // TODO: default should be module/config.ini
}
$filename = Module::get($name)->getConfigDir() . '/' . $file;
if (file_exists($filename)) {
$config = new Config($filename);
// Compat: $config->$module->$whatever
self::getInstance()->$name = $config;
return $config;
}
return null;
}
public function __get($key)
{
$res = parent::__get($key);
if ($res === null) {
$app = Icinga::app();
if ($app->hasModule($key)) {
$filename = $app->getModule($key)->getConfigDir() . "/$key.ini";
} else {
$filename = $this->configDir . '/' . $key . '.ini';
}
if (file_exists($filename)) {
$res = $this->$key = new Config($filename);
}
}
return $res;
}
public static function getInstance($configFile = null)
{
if (self::$instance === null) {
if ($configFile === null) {
$configFile = dirname(dirname(dirname(dirname(__FILE__))))
. '/config/icinga.ini';
}
self::$instance = new Config($configFile);
}
return self::$instance;
}
} }

View File

@ -113,14 +113,16 @@ class Module
} }
$this->registerLocales() $this->registerLocales()
->registerRoutes(); ->registerRoutes()
// ->registerMenuEntries(); ->registerMenuEntries();
return $this; return $this;
} }
protected function registerMenuEntries() protected function registerMenuEntries()
{ {
$cfg = $this->getConfig('menu.ini'); $cfg = $this->app
->getConfig()
->module($this->name, 'menu');
$view = $this->app->getView(); $view = $this->app->getView();
if ($cfg) { if ($cfg) {
$view->view->navigation = $cfg->merge($view->view->navigation); $view->view->navigation = $cfg->merge($view->view->navigation);

View File

@ -181,7 +181,7 @@ class Web extends ApplicationBootstrap
$this->config->{'global'}->get('project', 'Icinga') $this->config->{'global'}->get('project', 'Icinga')
); );
$view->view->headTitle()->setSeparator(' :: '); $view->view->headTitle()->setSeparator(' :: ');
$view->view->navigation = $this->config->menu; $view->view->navigation = $this->config->app('menu');
$this->view = $view; $this->view = $view;
return $this; return $this;

View File

@ -91,9 +91,9 @@ class LdapUserBackend implements UserBackend
protected function selectUsername($username) protected function selectUsername($username)
{ {
return $this->connection->select() return $this->connection->select()
->from(IcingaConfig::getInstance()->authentication->users->user_class, ->from(IcingaConfig::app('authentication')->users->user_class,
array(IcingaConfig::getInstance()->authentication->users->user_name_attribute)) array(IcingaConfig::app('authentication')->users->user_name_attribute))
->where(IcingaConfig::getInstance()->authentication->users->user_name_attribute, ->where(IcingaConfig::app('authentication')->users->user_name_attribute,
$this->stripAsterisks($username)); $this->stripAsterisks($username));
} }

View File

@ -25,8 +25,8 @@
namespace Icinga\Authentication; namespace Icinga\Authentication;
use Icinga\Application\Logger as Logger; use Icinga\Application\Logger;
use Icinga\Application\Config as Config; use Icinga\Application\Config as IcingaConfig;
use Icinga\Exception\ConfigurationError as ConfigError; use Icinga\Exception\ConfigurationError as ConfigError;
/** /**
@ -81,7 +81,7 @@ class Manager
* configuration provided in the authentication.ini if no config is given) * configuration provided in the authentication.ini if no config is given)
* and with the given options. * and with the given options.
* *
* @param Icinga\Config $config The configuration to use for authentication * @param IcingaConfig $config The configuration to use for authentication
* instead of the authentication.ini * instead of the authentication.ini
* @param Array $options Additional options that affect the managers behaviour. * @param Array $options Additional options that affect the managers behaviour.
* Supported values: * Supported values:
@ -95,7 +95,7 @@ class Manager
private function __construct($config = null, array $options = array()) private function __construct($config = null, array $options = array())
{ {
if ($config === null) { if ($config === null) {
$config = Config::getInstance()->authentication; $config = IcingaConfig::app('authentication');
} }
if (isset($options["userBackendClass"])) { if (isset($options["userBackendClass"])) {
$this->userBackend = $options["userBackendClass"]; $this->userBackend = $options["userBackendClass"];

View File

@ -2,7 +2,7 @@
namespace Icinga; namespace Icinga;
use Icinga\Application\Config; use Icinga\Application\Config as IcingaConfig;
use Icinga\Authentication\Manager as AuthManager; use Icinga\Authentication\Manager as AuthManager;
class Backend class Backend
@ -14,15 +14,15 @@ class Backend
public static function getInstance($name = null) public static function getInstance($name = null)
{ {
if (! array_key_exists($name, self::$instances)) { if (! array_key_exists($name, self::$instances)) {
$config = Config::getInstance()->backends; $backends = IcingaConfig::app('backends');
if ($name === null) { if ($name === null) {
$name = AuthManager::getInstance()->getSession()->get('backend'); $name = AuthManager::getInstance()->getSession()->get('backend');
} }
if ($name === null) { if ($name === null) {
$name = array_shift(array_keys($config->toArray())); $name = array_shift(array_keys($backends->toArray()));
} }
if (isset($config->backends->$name)) { if (isset($backends->$name)) {
$config = $config->backends->$name; $config = $backends->$name;
$type = $config->type; $type = $config->type;
$type[0] = strtoupper($type[0]); $type[0] = strtoupper($type[0]);
$class = '\\Icinga\\Backend\\' . $type; $class = '\\Icinga\\Backend\\' . $type;

View File

@ -1,5 +1,26 @@
<?php <?php
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
/**
* Icinga 2 Web - Head for multiple monitoring frontends
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web; namespace Icinga\Web;
@ -114,7 +135,7 @@ class ActionController extends ZfController
*/ */
protected function loadConfig() protected function loadConfig()
{ {
$this->config = Config::getInstance(); $this->config = Config::app();
} }
/** /**

View File

@ -5,7 +5,7 @@
*/ */
namespace Icinga\Web; namespace Icinga\Web;
use Icinga\Application\Config; use Icinga\Application\Config as IcingaConfig;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
/** /**
@ -64,7 +64,7 @@ class ModuleActionController extends ActionController
*/ */
protected function loadConfig() protected function loadConfig()
{ {
$this->config = Config::module($this->module_name); $this->config = IcingaConfig::module($this->module_name);
} }
/** /**

View File

@ -2,7 +2,7 @@
namespace Icinga\Monitoring; namespace Icinga\Monitoring;
use Icinga\Application\Config; use Icinga\Application\Config as IcingaConfig;
use Icinga\Authentication\Manager as AuthManager; use Icinga\Authentication\Manager as AuthManager;
use Exception; use Exception;
@ -36,8 +36,7 @@ class Backend
public function getBackendConfigs() public function getBackendConfigs()
{ {
if (self::$backendConfigs === null) { if (self::$backendConfigs === null) {
$config = Config::getInstance()->backends; $backends = IcingaConfig::app('backends');
$backends = $config->backends;
foreach ($backends as $name => $config) { foreach ($backends as $name => $config) {
// TODO: Check if access to this backend is allowed // TODO: Check if access to this backend is allowed
self::$backendConfigs[$name] = $config; self::$backendConfigs[$name] = $config;

View File

@ -3,7 +3,7 @@
use Icinga\Application\EmbeddedWeb; use Icinga\Application\EmbeddedWeb;
require_once dirname(__FILE__) . '/../library/Icinga/Application/EmbeddedWeb.php'; require_once dirname(__FILE__) . '/../library/Icinga/Application/EmbeddedWeb.php';
$app = EmbeddedWeb::start(); $app = EmbeddedWeb::start(dirname(__FILE__) . '/../config/');
require_once 'vendor/lessphp/lessc.inc.php'; require_once 'vendor/lessphp/lessc.inc.php';
header('Content-type: text/css'); header('Content-type: text/css');
$less = new lessc; $less = new lessc;

View File

@ -7,4 +7,4 @@ require_once dirname(__FILE__). '/../library/Icinga/Application/Web.php';
use Icinga\Application\Web; use Icinga\Application\Web;
Web::start()->dispatch(); Web::start(dirname(__FILE__) . '/../config/')->dispatch();

View File

@ -0,0 +1,7 @@
[logging]
enable = 1
[backend]
db.user = 'user'
db.password = 'password'
disable = 1

View File

@ -0,0 +1,2 @@
[meta]
version = 1

View File

@ -0,0 +1,2 @@
[menu]
breadcrumb = 1

View File

@ -0,0 +1,2 @@
[ldap]
user.ldap_object_class = inetOrgPerson

View File

@ -1,50 +1,86 @@
<?php <?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Application; namespace Tests\Icinga\Application;
/**
* require_once 'Zend/Config/Ini.php';
* Test class for Config require_once dirname(__FILE__) . '/../../../../../library/Icinga/Application/Config.php';
* Created Thu, 07 Feb 2013 10:07:13 +0000
* use Icinga\Application\Config as IcingaConfig;
**/
class ConfigTest extends \PHPUnit_Framework_TestCase class ConfigTest extends \PHPUnit_Framework_TestCase
{ {
public function setUp()
/**
* Test for Config::ListAll()
*
**/
public function testListAll()
{ {
$this->markTestIncomplete('testListAll is not implemented yet'); IcingaConfig::$configDir = dirname(__FILE__) . '/Config/files';
} }
/** public function testAppConfig()
* Test for Config::GetConfigDir()
*
**/
public function testGetConfigDir()
{ {
$this->markTestIncomplete('testGetConfigDir is not implemented yet'); $config = IcingaConfig::app();
$this->assertEquals(1, $config->logging->enable);
// Test non-existent property where null is the default value
$this->assertEquals(null, $config->logging->get('disable'));
// Test non-existent property using zero as the default value
$this->assertEquals(0, $config->logging->get('disable', 0));
// Test retrieve full section
$this->assertEquals(
array(
'disable' => 1,
'db' => array(
'user' => 'user',
'password' => 'password'
)
),
$config->backend->toArray()
);
// Test non-existent section using 'default' as default value
$this->assertEquals('default', $config->get('magic', 'default'));
// Test sub-properties
$this->assertEquals('user', $config->backend->db->user);
// Test non-existent sub-property using 'UTF-8' as the default value
$this->assertEquals('UTF-8', $config->backend->db->get('encoding', 'UTF-8'));
// Test invalid property names using false as default value
$this->assertEquals(false, $config->backend->get('.', false));
$this->assertEquals(false, $config->backend->get('db.', false));
$this->assertEquals(false, $config->backend->get('.user', false));
// Test retrieve array of sub-properties
$this->assertEquals(
array(
'user' => 'user',
'password' => 'password'
),
$config->backend->db->toArray()
);
// Test singleton
$this->assertEquals($config, IcingaConfig::app());
$this->assertEquals(array('logging', 'backend'), $config->keys());
$this->assertEquals(array('enable'), $config->keys('logging'));
} }
/** public function testAppExtraConfig()
* Test for Config::__get()
*
**/
public function test__get()
{ {
$this->markTestIncomplete('test__get is not implemented yet'); $extraConfig = IcingaConfig::app('extra');
$this->assertEquals(1, $extraConfig->meta->version);
$this->assertEquals($extraConfig, IcingaConfig::app('extra'));
} }
/** public function testModuleConfig()
* Test for Config::GetInstance()
* Note: This method is static!
*
**/
public function testGetInstance()
{ {
$this->markTestIncomplete('testGetInstance is not implemented yet'); $moduleConfig = IcingaConfig::module('amodule');
$this->assertEquals(1, $moduleConfig->menu->get('breadcrumb'));
$this->assertEquals($moduleConfig, IcingaConfig::module('amodule'));
} }
public function testModuleExtraConfig()
{
$moduleExtraConfig = IcingaConfig::module('amodule', 'extra');
$this->assertEquals(
'inetOrgPerson',
$moduleExtraConfig->ldap->user->get('ldap_object_class')
);
$this->assertEquals($moduleExtraConfig, IcingaConfig::module('amodule', 'extra'));
}
} }

View File

@ -1,50 +0,0 @@
<?php
namespace Tests\Icinga;
/**
*
* Test class for Config
* Created Wed, 16 Jan 2013 15:15:16 +0000
*
**/
class ConfigTest extends \PHPUnit_Framework_TestCase
{
/**
* Test for Config::Get()
*
**/
public function testGet()
{
$this->markTestIncomplete('testGet is not implemented yet');
}
/**
* Test for Config::__get()
*
**/
public function test__get()
{
$this->markTestIncomplete('test__get is not implemented yet');
}
/**
* Test for Config::__set()
*
**/
public function test__set()
{
$this->markTestIncomplete('test__set is not implemented yet');
}
/**
* Test for Config::Create()
* Note: This method is static!
*
**/
public function testCreate()
{
$this->markTestIncomplete('testCreate is not implemented yet');
}
}