From 2bc57d459b66ecff4878bd6d8e2d83b3a6d62554 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:18:36 +0200 Subject: [PATCH 01/92] QuickForm: translate() makes use of module name --- library/Director/Web/Form/QuickForm.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index 93c32a79..dfbdc4f2 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -60,10 +60,13 @@ abstract class QuickForm extends Zend_Form */ protected $icingaModule; + protected $icingaModuleName; + public function __construct($options = null) { if ($options !== null && array_key_exists('icingaModule', $options)) { $this->icingaModule = $options['icingaModule']; + $this->icingaModuleName = $this->icingaModule->getName(); unset($options['icingaModule']); } parent::__construct($options); @@ -254,8 +257,11 @@ abstract class QuickForm extends Zend_Form public function translate($string) { - // TODO: A module should use it's own domain - return t($string); + if ($this->icingaModuleName === null) { + return t($string); + } else { + return mt($this->icingaModuleName, $string); + } } public function onSuccess() From 5dcc9b35d90e481313240602909f2359b0d311bf Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:19:34 +0200 Subject: [PATCH 02/92] Db: template tree should be generic --- library/Director/Db.php | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/library/Director/Db.php b/library/Director/Db.php index 762dbfa4..8345a776 100644 --- a/library/Director/Db.php +++ b/library/Director/Db.php @@ -85,50 +85,51 @@ class Db extends DbConnection return $db->fetchOne($query); } - public function fetchHostTemplateTree() + public function fetchTemplateTree($type) { $db = $this->db(); $query = $db->select()->from( - array('ph' => 'icinga_host'), + array('p' => 'icinga_' . $type), array( - 'host' => 'h.object_name', - 'parent' => 'ph.object_name' + 'name' => 'o.object_name', + 'parent' => 'p.object_name' ) )->join( - array('hi' => 'icinga_host_inheritance'), - 'ph.id = hi.parent_host_id', + array('i' => 'icinga_' . $type . '_inheritance'), + 'p.id = i.parent_' . $type . '_id', array() )->join( - array('h' => 'icinga_host'), - 'h.id = hi.host_id', + array('o' => 'icinga_' . $type), + 'o.id = i.' . $type . '_id', array() - )->where("h.object_type = 'template'") - ->order('ph.object_name') - ->order('h.object_name'); + )->where("o.object_type = 'template'") + ->order('p.object_name') + ->order('o.object_name'); $relations = $db->fetchAll($query); $children = array(); - $hosts = array(); + $objects = array(); foreach ($relations as $rel) { - foreach (array('host', 'parent') as $col) { - if (! array_key_exists($rel->$col, $hosts)) { - $hosts[$rel->$col] = (object) array( + foreach (array('name', 'parent') as $col) { + if (! array_key_exists($rel->$col, $objects)) { + $objects[$rel->$col] = (object) array( 'name' => $rel->$col, 'children' => array() ); } } } + foreach ($relations as $rel) { - $hosts[$rel->parent]->children[$rel->host] = $hosts[$rel->host]; - $children[$rel->host] = $rel->parent; + $objects[$rel->parent]->children[$rel->name] = $objects[$rel->name]; + $children[$rel->name] = $rel->parent; } - foreach ($children as $name => $host) { - unset($hosts[$name]); + foreach ($children as $name => $object) { + unset($objects[$name]); } - return $hosts; + return $objects; } public function fetchLatestImportedRows($source, $columns = null) From a2cc9a612a274194844344b2c7998eafa048817a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:31:50 +0200 Subject: [PATCH 03/92] DirectorObjectForm: move optionalEnum to QuickForm --- library/Director/Web/Form/DirectorObjectForm.php | 7 ------- library/Director/Web/Form/QuickForm.php | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index d3765d8c..d9c581c7 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -148,13 +148,6 @@ abstract class DirectorObjectForm extends QuickForm $this->redirectOnSuccess($msg); } - protected function optionalEnum($enum) - { - return array( - null => $this->translate('- please choose -') - ) + $enum; - } - protected function optionalBoolean($key, $label, $description) { return $this->addElement('select', $key, array( diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index dfbdc4f2..fae99532 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -162,6 +162,13 @@ abstract class QuickForm extends Zend_Form return $this; } + public function optionalEnum($enum) + { + return array( + null => $this->translate('- please choose -') + ) + $enum; + } + public function setSuccessUrl($url) { $this->successUrl = $url; From cb8077057c1f07a5c88e52587f1af4da9d704c51 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:33:35 +0200 Subject: [PATCH 04/92] Db: fix enumImportSource --- library/Director/Db.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Director/Db.php b/library/Director/Db.php index 8345a776..0c762527 100644 --- a/library/Director/Db.php +++ b/library/Director/Db.php @@ -310,7 +310,7 @@ class Db extends DbConnection public function enumImportSource() { - return $this->enum('source_name', array('id', 'source_name')); + return $this->enum('import_source', array('id', 'source_name')); } public function enumDatalist() From 58f19a92708ca1025d7eb515c5f6d898ee03da1f Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:35:02 +0200 Subject: [PATCH 05/92] css/module.less: errors, textarea height --- public/css/module.less | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/public/css/module.less b/public/css/module.less index e89f29d5..6cd78e6a 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -17,8 +17,21 @@ form dd:after { display: block; content: ''; } -textarea { - height: 10em; + +form textarea { + height: auto; +} + +form dd ul.errors { + list-style-type: none; + padding-left: 0.3em; + font-size: 0.857em; + + li { + color: @colorCritical; + padding: 0.3em; + } +} } /* END of Forms */ From 9d9c23eed6ba1cf6e2f93b660a0f7d721174576b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:35:56 +0200 Subject: [PATCH 06/92] IcingaHostTemplateTable: first template only table --- application/tables/IcingaHostTemplateTable.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 application/tables/IcingaHostTemplateTable.php diff --git a/application/tables/IcingaHostTemplateTable.php b/application/tables/IcingaHostTemplateTable.php new file mode 100644 index 00000000..191eda59 --- /dev/null +++ b/application/tables/IcingaHostTemplateTable.php @@ -0,0 +1,13 @@ +getUnfilteredQuery()->where('h.object_type = ?', 'template'); + } +} From c9dd2e284c4d080418506456c6724190f40e17a1 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:38:30 +0200 Subject: [PATCH 07/92] QuickForm: addHtmlHint helper method --- library/Director/Web/Form/QuickForm.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index fae99532..f2e6ae41 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -62,6 +62,8 @@ abstract class QuickForm extends Zend_Form protected $icingaModuleName; + protected $hintCount = 0; + public function __construct($options = null) { if ($options !== null && array_key_exists('icingaModule', $options)) { @@ -162,6 +164,18 @@ abstract class QuickForm extends Zend_Form return $this; } + public function addHtmlHint($html, $options = array()) + { + $name = '_HINT' . ++$this->hintCount; + $this->addElement('note', $name, $options); + $this->getElement($name) + ->setValue('
' . $html . '
') + ->setIgnore(true) + ->removeDecorator('Label'); + + return $this; + } + public function optionalEnum($enum) { return array( From e98401d291e63486f210f7213aa47a60df1143e6 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:50:59 +0200 Subject: [PATCH 08/92] DirectorObjectForm: add setElementValue() helper --- .../Director/Web/Form/DirectorObjectForm.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index d9c581c7..0956edb8 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -129,6 +129,35 @@ abstract class DirectorObjectForm extends QuickForm } } + protected function setElementValue($name, $value = null, $inherited = null) + { + $el = $this->getElement($name); + if (! $el) { + return; + } + + if ($value !== null) { + $el->setValue($value); + } + + if ($inherited === null) { + return; + } + + $strInherited = $this->translate('(inherited)'); + if ($el instanceof Zf_Select) { + $multi = $el->getMultiOptions(); + if (array_key_exists($inherited, $multi)) { + $multi[null] = $multi[$inherited] . ' ' . $strInherited; + } else { + $multi[null] = $strInherited; + } + $el->setMultiOptions($multi); + } else { + $el->setAttrib('placeholder', $inherited . ' ' . $strInherited); + } + } + public function onSuccess() { $object = $this->object; From 6da851a6f7406d2756e682f450e0aa7ae4c3bb22 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:51:57 +0200 Subject: [PATCH 09/92] DatafieldTable: show more meaningful columns --- application/tables/DatafieldTable.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/application/tables/DatafieldTable.php b/application/tables/DatafieldTable.php index 72f5bd37..3b38598b 100644 --- a/application/tables/DatafieldTable.php +++ b/application/tables/DatafieldTable.php @@ -13,9 +13,11 @@ class DatafieldTable extends QuickTable public function getColumns() { return array( - 'id' => 'f.id', - 'varname' => 'f.varname', - 'datatype' => 'f.datatype', + 'id' => 'f.id', + 'varname' => 'f.varname', + 'caption' => 'f.caption', + 'description' => 'f.description', + 'datatype' => 'f.datatype', ); } @@ -28,8 +30,8 @@ class DatafieldTable extends QuickTable { $view = $this->view(); return array( - 'varname' => $view->translate('Field name'), - 'datatype' => $view->translate('Data type'), + 'caption' => $view->translate('Label'), + 'varname' => $view->translate('Field name'), ); } @@ -40,7 +42,7 @@ class DatafieldTable extends QuickTable $query = $db->select()->from( array('f' => 'director_datafield'), array() - )->order('varname ASC'); + )->order('caption ASC'); return $query; } From 3c5a825f040b3228b303c4a4be65d4b1cd648d48 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 08:53:05 +0200 Subject: [PATCH 10/92] SettingsContoller: form should be a form... ...also added a LOT of userfriendly hints, errors and notes --- .../controllers/SettingsController.php | 43 +---- application/forms/ConfigForm.php | 150 ++++++++++++++++++ 2 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 application/forms/ConfigForm.php diff --git a/application/controllers/SettingsController.php b/application/controllers/SettingsController.php index 42e64a9a..f86fb3a6 100644 --- a/application/controllers/SettingsController.php +++ b/application/controllers/SettingsController.php @@ -1,6 +1,5 @@ view->tabs = $this->Module()->getConfigTabs()->activate('config'); + $this->view->tabs = $this->Module() + ->getConfigTabs() + ->activate('config'); - $resource = $this->Config()->get('db', 'resource'); - - $form = new ConfigForm(); - - $form->setIniConfig($this->Config('config')); - $form->addElement('select', 'resource', array( - 'required' => true, - 'label' => $this->translate('DB Resource'), - 'multiOptions' => array(null => $this->translate('- please choose -')) + $this->getResources(), - 'value' => $resource - )); - $form->setSubmitLabel($this->translate('Save')); - - $form->setOnSuccess(function($form) { - /** @var $form ConfigForm */ - $this->Config('config')->setSection('db', array( - 'resource' => $form->getValue('resource') - )); - $form->save(); - }); - - $form->handleRequest(); - - $this->view->form = $form; - } - - public function getResources() - { - $resources = array(); - foreach (ResourceFactory::getResourceConfigs() as $name => $resource) { - if ($resource->type === 'db') { - $resources['ido'][$name] = $name; - } - } - return $resources; + $this->view->form = $this->loadForm('config') + ->setModuleConfig($this->Config()) + ->handleRequest(); } } diff --git a/application/forms/ConfigForm.php b/application/forms/ConfigForm.php new file mode 100644 index 00000000..a5941548 --- /dev/null +++ b/application/forms/ConfigForm.php @@ -0,0 +1,150 @@ +enumResources(); + + $this->addElement('select', 'resource', array( + 'required' => true, + 'label' => $this->translate('DB Resource'), + 'multiOptions' => $this->optionalEnum($resources), + 'class' => 'autosubmit', + 'value' => $this->config()->get('db', 'resource') + )); + + if (empty($resources)) { + $this->getElement('resource')->addError( + $this->translate('This has to be a MySQL or PostgreSQL database') + ); + + $hint = $this->translate('Please click %s to create new DB resources'); + $link = $this->getView()->qlink( + $this->translate('here'), + 'config/resource', + null, + array('data-base-target' => '_main') + ); + $this->addHtmlHint(sprintf($hint, $link)); + } + + $this->setSubmitLabel($this->translate('Store configuration')); + } + + protected function onSetup() + { + if ($this->hasBeenSubmitted()) { + // Do not hinder the form from being stored + return; + } + + if ($this->hasBeenSent() && $this->isValidPartial($this->getRequest()->getPost())) { + $resourceName = $this->getValue('resource'); + } else { + $resourceName = $this->config()->get('db', 'resource'); + } + + if ($resourceName) { + $resource = ResourceFactory::create($resourceName); + $db = $resource->getDbAdapter(); + + try { + $query = $db->select()->from('director_dbversion', 'COUNT(*)'); + $db->fetchOne($query); + + if (! $this->hasBeenSent()) { + $hint = $this->translate( + 'Configuration looks good, you should be ready to %s' + . ' Icinga Director' + ); + $link = $this->getView()->qlink( + $this->translate('start using'), + 'director/welcome', + null, + array('data-base-target' => '_main') + ); + $this->addHtmlHint(sprintf($hint, $link)); + $this->moveSubmitToBottom(); + } + + } catch (Exception $e) { + $this->getElement('resource') + ->addError('Could not fetch: ' . $e->getMessage()) + ->removeDecorator('description'); + + $hint = $this->translate( + 'Please make sure that your database grants enough permissions' + . ' and that you deployed the correct %s.' + ); + $link = $this->getView()->qlink( + $this->translate('database schema'), + 'director/schema/' . $resource->getDbType() + ); + $this->addHtmlHint(sprintf($hint, $link)); + $this->moveSubmitToBottom(); + } + } + } + + public function setModuleConfig(Config $config) + { + $this->config = $config; + return $this; + } + + public function onSuccess() + { + $config = $this->config(); + $value = $this->getValue('resource'); + + $config->setSection('db', array('resource' => $value)); + + try { + $config->saveIni(); + $this->redirectOnSuccess($this->translate('Configuration has been stored')); + } catch (Exception $e) { + $this->getElement('resource')->addError( + sprintf( + $this->translate('Unable to store the configuration to "%s"'), + $config->getConfigFile() + ) + )->removeDecorator('description'); + $this->addHtmlHint( + '
' . $config . '
' + ); + } + } + + protected function config() + { + if ($this->config === null) { + $this->config = Config::module('director'); + } + + return $this->config; + } + + protected function enumResources() + { + $resources = array(); + $allowed = array('mysql', 'pgsql'); + + foreach (ResourceFactory::getResourceConfigs() as $name => $resource) { + if ($resource->type === 'db' && in_array($resource->db, $allowed)) { + $resources[$name] = $name; + } + } + + return $resources; + } +} From 0bc2fbe9c7e27029c087d468c33840144a9fb4f2 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:04:42 +0200 Subject: [PATCH 11/92] Util: add auth helper methods --- library/Director/Util.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/Director/Util.php b/library/Director/Util.php index 6053a74b..2e2e8e2b 100644 --- a/library/Director/Util.php +++ b/library/Director/Util.php @@ -2,10 +2,13 @@ namespace Icinga\Module\Director; +use Icinga\Authentication\Manager; use Zend_Db_Expr; class Util { + protected static $auth; + public static function pgBinEscape($binary) { return new \Zend_Db_Expr("'\\x" . bin2hex($binary) . "'"); @@ -20,4 +23,22 @@ class Util { return current(unpack('H*', $hex)); } + + public static function auth() + { + if (self::$auth === null) { + self::$auth = Manager::getInstance(); + } + return self::$auth; + } + + public static function hasPermission($name) + { + return self::auth()->hasPermission($name); + } + + public static function getRestrictions($name) + { + return self::auth()->getRestrictions($name); + } } From ef28a18af241340a58b56a83789876401f511f98 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:05:32 +0200 Subject: [PATCH 12/92] configuration.php: add permissions/restrictions --- configuration.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/configuration.php b/configuration.php index f91ff7d1..4d0988fe 100644 --- a/configuration.php +++ b/configuration.php @@ -1,7 +1,20 @@ providePermission('director/templates', 'Allow to modify templates'); +$this->providePermission('director/hosts/read', $this->translate('Allow to configure hosts')); +$this->providePermission('director/hosts/write', $this->translate('Allow to configure hosts')); +$this->providePermission('director/templates/read', $this->translate('Allow to see template details')); +$this->providePermission('director/templates/write', $this->translate('Allow to configure templates')); + +$this->provideRestriction( + 'director/hosttemplates/filter', + $this->translate('Allow to use only host templates matching this filter') +); + +$this->provideRestriction( + 'director/dbresources/use', + $this->translate('Allow to use only these db resources (comma separated list)') +); + $this->provideConfigTab('config', array( 'title' => 'Configuration', From 9cfaf4d71f43ae6beb3ff8de3a1ad6abae8dd5aa Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:07:00 +0200 Subject: [PATCH 13/92] DirectorDatafieldForm: textarea height, code cleanup --- application/forms/DirectorDatafieldForm.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/application/forms/DirectorDatafieldForm.php b/application/forms/DirectorDatafieldForm.php index 71feb9a0..57bbc170 100644 --- a/application/forms/DirectorDatafieldForm.php +++ b/application/forms/DirectorDatafieldForm.php @@ -10,19 +10,20 @@ class DirectorDatafieldForm extends DirectorObjectForm public function setup() { $this->addElement('text', 'varname', array( - 'required' => true, - 'label' => $this->translate('Field name'), - 'description' => $this->translate('The unique name of the field') + 'label' => $this->translate('Field name'), + 'description' => $this->translate('The unique name of the field'), + 'required' => true, )); $this->addElement('text', 'caption', array( - 'label' => $this->translate('Caption'), + 'label' => $this->translate('Caption'), 'description' => $this->translate('The caption which should be displayed') )); $this->addElement('textarea', 'description', array( - 'label' => $this->translate('Description'), - 'description' => $this->translate('A description about the field') + 'label' => $this->translate('Description'), + 'description' => $this->translate('A description about the field'), + 'rows' => '3', )); $this->addElement('select', 'datatype', array( @@ -30,7 +31,7 @@ class DirectorDatafieldForm extends DirectorObjectForm 'description' => $this->translate('Field type'), 'required' => true, 'multiOptions' => $this->enumDataTypes(), - 'class' => 'autosubmit' + 'class' => 'autosubmit', )); if ($class = $this->object()->datatype) { From 92f53f18d151e5806bdf31ad174aef9e2d463da1 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:08:27 +0200 Subject: [PATCH 14/92] IcingaObjects: add supportsFields(), but still... ...unsure whether this shouldn't be implicitely depend on supportsCustomVars --- library/Director/Objects/IcingaObject.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index f41ecafa..88541a55 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -23,6 +23,8 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer protected $supportsImports = false; + protected $supportsFields = false; + private $type; private $vars; @@ -55,6 +57,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->supportsImports; } + public function supportsFields() + { + return $this->supportsFields; + } + public function hasBeenModified() { if ($this->supportsCustomVars() && $this->vars !== null && $this->vars()->hasBeenModified()) { From 7058536530427a78fd39cfade88f8e5c79236348 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:09:44 +0200 Subject: [PATCH 15/92] IcingaObject: add getFields() lookup method --- library/Director/Objects/IcingaObject.php | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index 88541a55..09620d42 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -250,6 +250,39 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->getShortTableName() . '_id'; } + public function getFields() + { + $fields = (object) array(); + + if (! $this->supportsFields()) { + return $fields; + } + + $db = $this->getDb(); + + $query = $db->select()->from( + array('df' => 'director_datafield'), + array( + 'datafield_id' => 'f.datafield_id', + 'is_required' => 'f.is_required', + 'varname' => 'df.varname' + ) + )->join( + array('f' => $this->getTableName() . '_field'), + 'df.id = f.datafield_id', + array() + )->where('f.host_id = ?', (int) $this->id) + ->order('df.caption ASC'); + + $res = $db->fetchAll($query); + + foreach ($res as $r) { + $fields->{$r->varname} = $r; + } + + return $fields; + } + public function isTemplate() { return $this->hasProperty('object_type') From 18782b9ff5a40900358b47435a26240f5c99a831 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:10:57 +0200 Subject: [PATCH 16/92] QuickForm: add buttons before onSetup() hook --- library/Director/Web/Form/QuickForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index f2e6ae41..99bf7727 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -241,8 +241,8 @@ abstract class QuickForm extends Zend_Form { if (! $this->didSetup) { $this->setup(); - $this->onSetup(); $this->addSubmitButtonIfSet(); + $this->onSetup(); $this->didSetup = true; } From cc9b783f699ca5172311ece8a98b04918b02796d Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:11:53 +0200 Subject: [PATCH 17/92] Util: a couple of db resource helpers --- library/Director/Util.php | 66 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/library/Director/Util.php b/library/Director/Util.php index 2e2e8e2b..2d8a5545 100644 --- a/library/Director/Util.php +++ b/library/Director/Util.php @@ -3,12 +3,16 @@ namespace Icinga\Module\Director; use Icinga\Authentication\Manager; +use Icinga\Data\ResourceFactory; +use Icinga\Module\Director\Web\Form\QuickForm; use Zend_Db_Expr; class Util { protected static $auth; + protected static $allowedDbResources; + public static function pgBinEscape($binary) { return new \Zend_Db_Expr("'\\x" . bin2hex($binary) . "'"); @@ -41,4 +45,66 @@ class Util { return self::auth()->getRestrictions($name); } + + public static function dbResourceIsAllowed($name) + { + if (self::$allowedDbResources === null) { + $restrictions = self::getRestrictions('director/dbresources/use'); + $list = array(); + foreach ($restrictions as $restriction) { + foreach (preg_split('/\s*,\s*/', $restriction, -1, PREG_SPLIT_NO_EMPTY) as $key) { + $list[$key] = $key; + } + } + + self::$allowedDbResources = $list; + } else { + $list = self::$allowedDbResources; + } + + if (empty($list) || array_key_exists($name, $list)) { + return true; + } + + return false; + } + + public static function enumDbResources() + { + $resources = array(); + foreach (ResourceFactory::getResourceConfigs() as $name => $resource) { + if ($resource->type === 'db' && self::dbResourceIsAllowed($name)) { + $resources[$name] = $name; + } + } + + return $resources; + } + + public static function addDbResourceFormElement(QuickForm $form, $name) + { + $list = Util::enumDbResources(); + + $form->addElement('select', $name, array( + 'label' => 'Resource name', + 'multiOptions' => $form->optionalEnum($list), + 'required' => true, + )); + + if (true && empty($list)) { + if (self::hasPermission('config/application/resources')) { + $hint = $form->translate('Please click %s to create new DB resources'); + $link = sprintf( + '%s', + $form->translate('here') + ); + $form->addHtmlHint(sprintf($hint, $link)); + $msg = $form->translate('No db resource available'); + } else { + $msg = $form->translate('Please ask an administrator to grant you access to DB resources'); + } + + $form->getElement($name)->addError($msg); + } + } } From 24cd6499087c347f1df34cf4ad99b571479ea2ce Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:12:19 +0200 Subject: [PATCH 18/92] Util: add missing use, remove backslash --- library/Director/Util.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/Director/Util.php b/library/Director/Util.php index 2d8a5545..8d74516e 100644 --- a/library/Director/Util.php +++ b/library/Director/Util.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Director; use Icinga\Authentication\Manager; use Icinga\Data\ResourceFactory; use Icinga\Module\Director\Web\Form\QuickForm; +use Icinga\Web\Url; use Zend_Db_Expr; class Util @@ -15,7 +16,7 @@ class Util public static function pgBinEscape($binary) { - return new \Zend_Db_Expr("'\\x" . bin2hex($binary) . "'"); + return new Zend_Db_Expr("'\\x" . bin2hex($binary) . "'"); } public static function hex2binary($bin) From 5a3fead131fbc725dbd26480a0e87fad22455996 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:22:55 +0200 Subject: [PATCH 19/92] DirectorObjectForm: allow to enforce object type... ...when creating new objects --- .../Director/Web/Form/DirectorObjectForm.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 0956edb8..ef270acf 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -14,6 +14,8 @@ abstract class DirectorObjectForm extends QuickForm private $className; + private $objectType = 'object'; + protected function object($values = array()) { if ($this->object === null) { @@ -64,6 +66,11 @@ abstract class DirectorObjectForm extends QuickForm } } + protected function isTemplate() + { + return $this->objectType === 'template'; + } + protected function handleIcingaObject(& $values) { $object = $this->object(); @@ -129,6 +136,12 @@ abstract class DirectorObjectForm extends QuickForm } } + public function setObjectType($type) + { + $this->objectType = $type; + return $this; + } + protected function setElementValue($name, $value = null, $inherited = null) { $el = $this->getElement($name); @@ -164,8 +177,12 @@ abstract class DirectorObjectForm extends QuickForm $values = $this->getValues(); if ($object instanceof IcingaObject) { $this->handleIcingaObject($values); + if (! array_key_exists('object_type', $values)) { + $object->object_type = $this->objectType; + } } $object->setProperties($values); + $msg = sprintf( $object->hasBeenLoadedFromDb() ? 'The Icinga %s has successfully been stored' @@ -228,7 +245,11 @@ abstract class DirectorObjectForm extends QuickForm { $this->prepareElements(); $class = $this->getObjectClassname(); - $this->object = $class::load($id, $this->db); + $object = $this->object = $class::load($id, $this->db); + if ($object instanceof IcingaObject) { + $this->objectType = $object->object_type; + } + if (! is_array($id)) { $this->addHidden('id'); } From 03436efa2939095e4df81791898b0396be4032a8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:26:02 +0200 Subject: [PATCH 20/92] ObjectController: distinct templates and objects --- .../Director/Web/Controller/ObjectController.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/Director/Web/Controller/ObjectController.php b/library/Director/Web/Controller/ObjectController.php index f46b61ed..d408635f 100644 --- a/library/Director/Web/Controller/ObjectController.php +++ b/library/Director/Web/Controller/ObjectController.php @@ -102,15 +102,19 @@ abstract class ObjectController extends ActionController $ltype = strtolower($type); $url = sprintf('director/%ss', $ltype); - $this->view->form = $this->loadForm('icinga' . ucfirst($type)) + $form = $this->view->form = $this->loadForm('icinga' . ucfirst($type)) ->setDb($this->db()) ->setSuccessUrl($url); - $this->view->title = sprintf( - $this->translate('Add new Icinga %s'), - ucfirst($ltype) - ); - $this->view->form->handleRequest(); + if ($this->params->get('type') === 'template') { + $form->setObjectType('template'); + $title = $this->translate('Add new Icinga %s'); + } else { + $title = $this->translate('Add new Icinga %s template'); + } + + $this->view->title = sprintf($title, ucfirst($ltype)); + $form->handleRequest(); $this->render('object/form', null, true); } From 918660e3bfda3c6e8d38c67aa6185940522a1249 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:45:32 +0200 Subject: [PATCH 21/92] ObjectsController: support template distinction --- .../Web/Controller/ObjectsController.php | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/library/Director/Web/Controller/ObjectsController.php b/library/Director/Web/Controller/ObjectsController.php index e40c48ff..f78f1ccc 100644 --- a/library/Director/Web/Controller/ObjectsController.php +++ b/library/Director/Web/Controller/ObjectsController.php @@ -66,23 +66,37 @@ abstract class ObjectsController extends ActionController { $type = $this->getType(); $ltype = strtolower($type); - + $dummy = $this->dummyObject(); if (! in_array($type, $this->globalTypes)) { - if ($this->dummyObject()->isGroup()) { + if ($dummy->isGroup()) { $this->getTabs()->activate('objectgroups'); + $table = 'icinga' . ucfirst($type); + } elseif ($dummy->isTemplate()) { + $this->getTabs()->activate('objecttemplates'); + $table = 'icinga' . ucfirst($type); + $this->loadTable($table); + $table = 'icinga' . ucfirst($type) . 'Template'; } else { $this->getTabs()->activate('objects'); } } + if ($dummy->isTemplate()) { + $addParams = array('type' => 'template'); + $addTitle = $this->translate('Add %s template'); + } else { + $addParams = array(); + $addTitle = $this->translate('Add %s'); + } + $this->view->addLink = $this->view->qlink( - $this->translate('Add ' . ucfirst($ltype)), - 'director/' . $ltype . '/add' + sprintf($addTitle, $this->translate(ucfirst($ltype))), + 'director/' . $ltype .'/add', + $addParams ); $this->view->title = $this->translate('Icinga ' . ucfirst($ltype)); - - $table = $this->loadTable('icinga' . ucfirst($type))->setConnection($this->db()); + $table = $this->loadTable($table)->setConnection($this->db()); $this->setupFilterControl($table->getFilterEditor($this->getRequest())); $this->view->table = $this->applyPaginationLimits($table); @@ -94,6 +108,13 @@ abstract class ObjectsController extends ActionController if ($this->dummy === null) { $class = $this->getObjectClassname(); $this->dummy = $class::create(array()); + if ($this->dummy->hasProperty('object_type')) { + if (false === strpos($this->getRequest()->getControllerName(), 'template')) { + $this->dummy->object_type = 'object'; + } else { + $this->dummy->object_type = 'template'; + } + } } return $this->dummy; @@ -105,7 +126,11 @@ abstract class ObjectsController extends ActionController return preg_replace( array('/group$/', '/period$/', '/argument$/'), array('Group', 'Period', 'Argument'), - substr($this->getRequest()->getControllerName(), 0, -1) + str_replace( + 'template', + '', + substr($this->getRequest()->getControllerName(), 0, -1) + ) ); } From fa9a6eeabbb2c0a0004380503c194571337874ca Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:46:14 +0200 Subject: [PATCH 22/92] ImportSourceSql: make use of new Util helpers --- library/Director/Import/ImportSourceSql.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/Director/Import/ImportSourceSql.php b/library/Director/Import/ImportSourceSql.php index 0fa36481..416dae3b 100644 --- a/library/Director/Import/ImportSourceSql.php +++ b/library/Director/Import/ImportSourceSql.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\Import; +use Icinga\Module\Director\Util; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Module\Director\Web\Hook\ImportSourceHook; use Icinga\Data\Db\DbConnection; @@ -23,13 +24,11 @@ class ImportSourceSql extends ImportSourceHook public static function addSettingsFormFields(QuickForm $form) { - $form->addElement('text', 'resource', array( - 'label' => 'Resource name', - 'required' => true, - )); + Util::addDbResourceFormElement($form, 'resource'); $form->addElement('textarea', 'query', array( 'label' => 'DB Query', 'required' => true, + 'rows' => 15, )); return $form; } From ceb22f830dc3f24ff61863d81e5bd2e488bcc6a6 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:47:06 +0200 Subject: [PATCH 23/92] DataTypeSqlQuery: set textarea rows, use Util::* --- library/Director/DataType/DataTypeSqlQuery.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/library/Director/DataType/DataTypeSqlQuery.php b/library/Director/DataType/DataTypeSqlQuery.php index d4026dea..06a61693 100644 --- a/library/Director/DataType/DataTypeSqlQuery.php +++ b/library/Director/DataType/DataTypeSqlQuery.php @@ -2,9 +2,10 @@ namespace Icinga\Module\Director\DataType; +use Icinga\Data\Db\DbConnection; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Module\Director\Web\Hook\DataTypeHook; -use Icinga\Data\Db\DbConnection; +use Icinga\Module\Director\Util; class DataTypeSqlQuery extends DataTypeHook { @@ -36,17 +37,13 @@ class DataTypeSqlQuery extends DataTypeHook public static function addSettingsFormFields(QuickForm $form) { - $db = $form->getDb(); - - $form->addElement('text', 'resource', array( - 'label' => 'Resource name', - 'required' => true, - )); + Util::addDbResourceFormElement($form, 'resource'); $form->addElement('textarea', 'query', array( 'label' => 'DB Query', 'description' => 'This query should return exactly two columns, value and label', 'required' => true, + 'rows' => 10, )); return $form; From b97cb14e0584c69242af874c02dc55c88e54a71a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:49:01 +0200 Subject: [PATCH 24/92] Objects: add template tree --- .../views/scripts/hosttemplates/tree.phtml | 65 +++++++++++++++++++ .../Web/Controller/ObjectsController.php | 17 +++-- 2 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 application/views/scripts/hosttemplates/tree.phtml diff --git a/application/views/scripts/hosttemplates/tree.phtml b/application/views/scripts/hosttemplates/tree.phtml new file mode 100644 index 00000000..a97bba7a --- /dev/null +++ b/application/views/scripts/hosttemplates/tree.phtml @@ -0,0 +1,65 @@ +children); + if ($level === 0) { + $class = 'root'; + } else { + $class = 'host'; + } + + if ($hasChildren) { + $collapsed = ''; + } else { + $collapsed = ' class="collapsed"'; + } + + $html = ''; + if ($hasChildren) { + ksort($tree->children); + $html .= ' '; + } + + if ($level === 0) { + $html .= '' . $self->escape($tree->name) . ''; + } else { + $html .= $self->qlink( + $tree->name, + 'director/host', + array('name' => $tree->name), + array('class' => $class) + ); + } + + if ($hasChildren) { + $html .= '
    '; + foreach ($tree->children as $child) { + $html .= dumpTree($child, $self, $level + 1); + } + $html .= '
'; + } + $html .= "\n"; + return $html; +} + +?> +
+tabs ?> +

translate('Host template tree') ?>

+
+ +
+
    + + 'Templates', + 'children' => $this->tree + ), + $this +) ?> +
+
diff --git a/library/Director/Web/Controller/ObjectsController.php b/library/Director/Web/Controller/ObjectsController.php index f78f1ccc..ec74945e 100644 --- a/library/Director/Web/Controller/ObjectsController.php +++ b/library/Director/Web/Controller/ObjectsController.php @@ -16,14 +16,12 @@ abstract class ObjectsController extends ActionController public function init() { + $tabs = $this->getTabs(); $type = $this->getType(); - $ltype = strtolower($type); - - $object = $this->dummyObject(); if (in_array(ucfirst($type), $this->globalTypes)) { + $ltype = strtolower($type); - $tabs = $this->getTabs(); foreach ($this->globalTypes as $tabType) { $ltabType = strtolower($tabType); $tabs->add($ltabType, array( @@ -60,6 +58,11 @@ abstract class ObjectsController extends ActionController } } + + $tabs->add('tree', array( + 'url' => sprintf('director/%stemplates/tree', $type), + 'label' => $this->translate('Tree'), + )); } public function indexAction() @@ -103,6 +106,12 @@ abstract class ObjectsController extends ActionController $this->render('objects/table', null, true); } + public function treeAction() + { + $this->getTabs()->activate('tree'); + $this->view->tree = $this->db()->fetchTemplateTree(strtolower($this->getType())); + } + protected function dummyObject() { if ($this->dummy === null) { From 3253bf2c88097266374c801f885f7daaab521a99 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:49:34 +0200 Subject: [PATCH 25/92] ObjectsController: reorganize tabs --- .../Web/Controller/ObjectsController.php | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/library/Director/Web/Controller/ObjectsController.php b/library/Director/Web/Controller/ObjectsController.php index ec74945e..7b3e364e 100644 --- a/library/Director/Web/Controller/ObjectsController.php +++ b/library/Director/Web/Controller/ObjectsController.php @@ -31,32 +31,28 @@ abstract class ObjectsController extends ActionController } $tabs->activate($ltype); - } elseif ($object->isGroup()) { + return; + } - $singleType = substr($type, 0, -5); - $tabs = $this->getTabs()->add('objects', array( - 'url' => sprintf('director/%ss', $singleType), - 'label' => $this->translate(ucfirst($singleType) . 's'), - )); + $object = $this->dummyObject(); + if ($object->isGroup()) { + $type = substr($type, 0, -5); + } + + $tabs = $this->getTabs()->add('objects', array( + 'url' => sprintf('director/%ss', strtolower($type)), + 'label' => $this->translate(ucfirst($type) . 's'), + )); + $tabs = $this->getTabs()->add('objecttemplates', array( + 'url' => sprintf('director/%stemplates', strtolower($type)), + 'label' => $this->translate('Templates'), + )); + if ($object->supportsGroups() || $object->isGroup()) { $tabs->add('objectgroups', array( - 'url' => sprintf('director/%ss', strtolower($type)), - 'label' => $this->translate(ucfirst(strtolower($type)) . 's') + 'url' => sprintf('director/%sgroups', $type), + 'label' => $this->translate('Groups') )); - - } else { - - $tabs = $this->getTabs()->add('objects', array( - 'url' => sprintf('director/%ss', strtolower($type)), - 'label' => $this->translate(ucfirst($type) . 's'), - )); - if ($object->supportsGroups()) { - $tabs->add('objectgroups', array( - 'url' => sprintf('director/%sgroups', $type), - 'label' => $this->translate(ucfirst($type) . 'groups') - )); - } - } $tabs->add('tree', array( @@ -82,7 +78,10 @@ abstract class ObjectsController extends ActionController $table = 'icinga' . ucfirst($type) . 'Template'; } else { $this->getTabs()->activate('objects'); + $table = 'icinga' . ucfirst($type); } + } else { + $table = 'icinga' . ucfirst($type); } if ($dummy->isTemplate()) { From 830fcad7ff14329be10ba4f5b2a071df4cdaa528 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:50:21 +0200 Subject: [PATCH 26/92] Menu: move Fields to bottom, will be removed --- configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration.php b/configuration.php index 4d0988fe..54f1a736 100644 --- a/configuration.php +++ b/configuration.php @@ -27,7 +27,7 @@ $section = $this->menuSection( $section->add($this->translate('Global'))->setUrl('director/commands'); $section->add($this->translate('Hosts'))->setUrl('director/hosts'); -$section->add($this->translate('Fields'))->setUrl('director/field/host'); +$section->add($this->translate('Fields'))->setUrl('director/field/host')->setPriority(903); $section->add($this->translate('Services'))->setUrl('director/services'); $section->add($this->translate('Users'))->setUrl('director/users'); $section->add($this->translate('Import / Sync')) From cdc9d002bc8c29bc8e1c5f1eb5bea66a6c81fc23 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 09:50:51 +0200 Subject: [PATCH 27/92] settings: fix nasty redirect target issue --- application/views/scripts/settings/index.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/views/scripts/settings/index.phtml b/application/views/scripts/settings/index.phtml index 37d437e0..9120812c 100644 --- a/application/views/scripts/settings/index.phtml +++ b/application/views/scripts/settings/index.phtml @@ -2,6 +2,6 @@ tabs ?> -
- +
+
From 0fc948b3d3788fab0d991c4c65828e4405afc702 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:03:31 +0200 Subject: [PATCH 28/92] IcingaCommandArgumentForm: cleanup, prefill enum --- application/forms/IcingaCommandArgumentForm.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/application/forms/IcingaCommandArgumentForm.php b/application/forms/IcingaCommandArgumentForm.php index 19eec1bf..c4f51b93 100644 --- a/application/forms/IcingaCommandArgumentForm.php +++ b/application/forms/IcingaCommandArgumentForm.php @@ -8,10 +8,10 @@ class IcingaCommandArgumentForm extends DirectorObjectForm { public function setup() { - $this->addElement('select', 'command_id', array( - 'label' => $this->translate('Check command'), - 'description' => $this->translate('Check command definition') + 'label' => $this->translate('Check command'), + 'description' => $this->translate('Check command definition'), + 'multiOptions' => $this->optionalEnum($this->db->enumCommands()) )); $this->addElement('text', 'argument_name', array( @@ -26,7 +26,6 @@ class IcingaCommandArgumentForm extends DirectorObjectForm )); $this->addHidden('value_format', 'string'); // expression, json? - } From d93e498688d6770f968218805dbd3970bfc94638 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:04:12 +0200 Subject: [PATCH 29/92] ObjectController: reorganize tabs Edit is the new default action, config snippet is "preview" --- .../Web/Controller/ObjectController.php | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/library/Director/Web/Controller/ObjectController.php b/library/Director/Web/Controller/ObjectController.php index d408635f..032ea127 100644 --- a/library/Director/Web/Controller/ObjectController.php +++ b/library/Director/Web/Controller/ObjectController.php @@ -16,18 +16,18 @@ abstract class ObjectController extends ActionController if ($name = $this->params->get('name')) { $params['name'] = $name; - $this->getTabs()->add($type, array( - 'url' => sprintf('director/%s', $ltype), - 'urlParams' => $params, - 'label' => $this->translate(ucfirst($ltype)), - ))->add('modify', array( + $this->getTabs()->add('modify', array( 'url' => sprintf('director/%s/edit', $ltype), 'urlParams' => $params, - 'label' => $this->translate('Modify') + 'label' => $this->translate(ucfirst($ltype)) ))->add('delete', array( 'url' => sprintf('director/%s/delete', $ltype), 'urlParams' => $params, 'label' => $this->translate('Delete') + ))->add('render', array( + 'url' => sprintf('director/%s/render', $ltype), + 'urlParams' => $params, + 'label' => $this->translate('Preview'), ))->add('history', array( 'url' => sprintf('director/%s/history', $ltype), 'urlParams' => $params, @@ -35,16 +35,21 @@ abstract class ObjectController extends ActionController )); } else { $this->getTabs()->add('add', array( - 'url' => sprintf('director/%s', $type), + 'url' => sprintf('director/%s/add', $type), 'label' => sprintf($this->translate('Add %s'), ucfirst($type)), )); } } public function indexAction() + { + return $this->editAction(); + } + + public function renderAction() { $type = $this->getType(); - $this->getTabs()->activate($type); + $this->getTabs()->activate('render'); $this->view->object = $this->object(); $this->render('object/show', null, true); } From d30d5c51c24b895f428ea1318692a349b4046fa3 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:07:44 +0200 Subject: [PATCH 30/92] DirectorObjectForm: add a bunch of helper methods --- .../Director/Web/Form/DirectorObjectForm.php | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index ef270acf..1cc9a1df 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -365,9 +365,98 @@ abstract class DirectorObjectForm extends QuickForm $this->getElement('command_id') ->setMultiOptions($this->optionalEnum($db->enumCommands())); } + return $this; } + protected function addZoneElement() + { + $this->addElement('select', 'zone_id', array( + 'label' => $this->translate('Cluster Zone'), + 'description' => $this->translate('Icinga cluster zone'), + 'multiOptions' => $this->optionalEnum($this->db->enumZones()) + )); + + return $this; + } + + protected function addCheckCommandElement() + { + $this->addElement('select', 'check_command_id', array( + 'label' => $this->translate('Check command'), + 'description' => $this->translate('Check command definition'), + 'multiOptions' => $this->optionalEnum($this->db->enumCheckCommands()) + )); + + return $this; + } + + protected function addImportsElement() + { + $this->addElement('multiselect', 'imports', array( + 'label' => $this->translate('Imports'), + 'description' => $this->translate('Importable templates'), + 'multiOptions' => $this->enumAllowedTemplates(), + 'class' => 'autosubmit' + )); + + return $this; + } + + protected function addCheckFlagElements() + { + $this->optionalBoolean( + 'enable_active_checks', + $this->translate('Execute active checks'), + $this->translate('Whether to actively check this object') + ); + + $this->optionalBoolean( + 'enable_passive_checks', + $this->translate('Accept passive checks'), + $this->translate('Whether to accept passive check results for this object') + ); + + $this->optionalBoolean( + 'enable_notifications', + $this->translate('Send notifications'), + $this->translate('Whether to send notifications for this object') + ); + + $this->optionalBoolean( + 'enable_event_handler', + $this->translate('Enable event handler'), + $this->translate('Whether to enable event handlers this object') + ); + + $this->optionalBoolean( + 'enable_perfdata', + $this->translate('Process performance data'), + $this->translate('Whether to process performance data provided by this object') + ); + + $this->optionalBoolean( + 'volatile', + $this->translate('Volatile'), + $this->translate('Whether this check is volatile.') + ); + + return $this; + } + + protected function enumAllowedTemplates() + { + $object = $this->object(); + $tpl = $this->db->enumIcingaTemplates($object->getShortTableName()); + $tpl = array_combine($tpl, $tpl); + $id = $object->object_name; + + if (array_key_exists($id, $tpl)) { + unset($tpl[$id]); + } + return $tpl; + } + private function dummyForTranslation() { $this->translate('Host'); From 44a9755cce8c1cbfbe70bad430b9d0348f534e87 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:09:44 +0200 Subject: [PATCH 31/92] QuickForm: no label for hints --- library/Director/Web/Form/QuickForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index 99bf7727..dcecf4c6 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -82,7 +82,7 @@ abstract class QuickForm extends Zend_Form { if (false !== ($label = $this->getSubmitLabel())) { $this->addElement('submit', $label); - $this->getElement($label)->setLabel($label); + $this->getElement($label)->setLabel($label)->removeDecorator('Label'); } } From 043a8e07e5d980f2a21bece1614b207d7fc1ed4c Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:10:34 +0200 Subject: [PATCH 32/92] IcingaEndpointForm: use new helpers --- application/forms/IcingaEndpointForm.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/application/forms/IcingaEndpointForm.php b/application/forms/IcingaEndpointForm.php index f792eac3..b64fe937 100644 --- a/application/forms/IcingaEndpointForm.php +++ b/application/forms/IcingaEndpointForm.php @@ -48,15 +48,7 @@ class IcingaEndpointForm extends DirectorObjectForm 'description' => $this->translate('The log duration time.') )); - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this host in this specific Icinga cluster zone'), - 'required' => true - )); - - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited endpoint template names') - )); + $this->addZoneElement() + ->addImportsElement(); } } From 1b56432b237e761780f0ea7ceaf5a9eb27339923 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:25:51 +0200 Subject: [PATCH 33/92] DatalistentryController: fix edit --- application/controllers/DatalistentryController.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/application/controllers/DatalistentryController.php b/application/controllers/DatalistentryController.php index 5d040f8f..1581d78c 100644 --- a/application/controllers/DatalistentryController.php +++ b/application/controllers/DatalistentryController.php @@ -11,19 +11,13 @@ class Director_DatalistentryController extends ActionController public function editAction() { - $this->indexAction(); + $this->indexAction(true); } public function indexAction($edit = false) { $request = $this->getRequest(); - if ($request->getParam('edit')) { - $edit = true; - } else { - $edit = false; - } - $listId = $this->params->get('list_id'); $this->view->lastId = $listId; From 8a3873fbc1c9f2c970b7684809f089d848065d1e Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 10:28:25 +0200 Subject: [PATCH 34/92] css/module.less: style hints --- public/css/module.less | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/public/css/module.less b/public/css/module.less index 6cd78e6a..7eed1405 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -32,6 +32,21 @@ form dd ul.errors { padding: 0.3em; } } + +form div.hint { + font-size: 0.857em; + padding: 1em; + background-color: #f2f4fd; + border: 1px solid lightgrey; + margin: 1em 0; + + pre { + font-style: normal; + background-color: white; + font-size: 1.25em; + margin: 0; + padding: 1em; + } } /* END of Forms */ From 9ca544e4e15690f83c693d6b5aa9f81d18bfbc61 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:32:05 +0200 Subject: [PATCH 35/92] activitylog: render arrays, required for groups --- application/views/scripts/show/activitylog-create.phtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/views/scripts/show/activitylog-create.phtml b/application/views/scripts/show/activitylog-create.phtml index 67efbc6a..5f92930d 100644 --- a/application/views/scripts/show/activitylog-create.phtml +++ b/application/views/scripts/show/activitylog-create.phtml @@ -15,6 +15,8 @@ foreach ($new as $key => $value) { if ($value === null) continue; + if (is_array($value)) $value = implode(', ', $value); + echo ' ' . $this->escape($key) . ''; echo $this->escape($value); echo "\n"; From 5b3806532f467a3f1f34da7daf12133400d23bb3 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:33:08 +0200 Subject: [PATCH 36/92] forms: cleanup, use new helpers --- application/forms/CustomvarForm.php | 26 ++++ application/forms/IcingaEndpointForm.php | 3 +- application/forms/IcingaHostFieldForm.php | 14 +-- application/forms/IcingaHostForm.php | 124 +++---------------- application/forms/IcingaHostGroupForm.php | 32 +---- application/forms/IcingaHostVarForm.php | 13 +- application/forms/IcingaServiceFieldForm.php | 13 +- application/forms/IcingaServiceForm.php | 53 +------- application/forms/IcingaServiceGroupForm.php | 32 +---- application/forms/IcingaServiceVarForm.php | 13 +- application/forms/IcingaTimePeriodForm.php | 12 +- application/forms/IcingaUserForm.php | 11 +- application/forms/IcingaUserGroupForm.php | 37 +----- application/forms/IcingaZoneForm.php | 15 +-- 14 files changed, 100 insertions(+), 298 deletions(-) create mode 100644 application/forms/CustomvarForm.php diff --git a/application/forms/CustomvarForm.php b/application/forms/CustomvarForm.php new file mode 100644 index 00000000..759464c9 --- /dev/null +++ b/application/forms/CustomvarForm.php @@ -0,0 +1,26 @@ +removeCsrfToken(); + $this->removeElement(self::ID); + $this->addElement('text', 'varname', array( + 'label' => $this->translate('Variable name'), + 'required' => true, + )); + + $this->addElement('text', 'varvalue', array( + 'label' => $this->translate('Value'), + )); + + // $this->addHidden('format', 'string'); // expression, json? + } +} diff --git a/application/forms/IcingaEndpointForm.php b/application/forms/IcingaEndpointForm.php index b64fe937..718116fb 100644 --- a/application/forms/IcingaEndpointForm.php +++ b/application/forms/IcingaEndpointForm.php @@ -8,7 +8,8 @@ class IcingaEndpointForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; + $isTemplate = $this->getSentValue('object_type') === 'template'; + $this->addElement('select', 'object_type', array( 'label' => $this->translate('Object type'), 'description' => $this->translate('Whether this should be a template'), diff --git a/application/forms/IcingaHostFieldForm.php b/application/forms/IcingaHostFieldForm.php index fb2f9713..5c7b8f08 100644 --- a/application/forms/IcingaHostFieldForm.php +++ b/application/forms/IcingaHostFieldForm.php @@ -9,21 +9,21 @@ class IcingaHostFieldForm extends DirectorObjectForm public function setup() { $this->addElement('select', 'host_id', array( - 'label' => 'Host Tpl', - 'description' => 'Host Template', - 'multiOptions' => $this->optionalEnum($this->getDb()->enumHostTemplates()) + 'label' => 'Host Tpl', + 'description' => 'Host Template', + 'multiOptions' => $this->optionalEnum($this->db->enumHostTemplates()) )); $this->addElement('select', 'datafield_id', array( - 'label' => 'Field', - 'description' => 'Field to assign', - 'multiOptions' => $this->optionalEnum($this->getDb()->enumDatafields()) + 'label' => 'Field', + 'description' => 'Field to assign', + 'multiOptions' => $this->optionalEnum($this->db->enumDatafields()) )); $this->optionalBoolean( 'is_required', $this->translate('Required'), - $this->translate('Whether this filed is required or not.') + $this->translate('Whether this field should be required or not') ); } } diff --git a/application/forms/IcingaHostForm.php b/application/forms/IcingaHostForm.php index d6f3cda2..3620512a 100644 --- a/application/forms/IcingaHostForm.php +++ b/application/forms/IcingaHostForm.php @@ -9,32 +9,12 @@ class IcingaHostForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; - $this->addElement('select', 'object_type', array( - 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), - 'multiOptions' => array( - null => '- please choose -', - 'object' => 'Host object', - 'template' => 'Host template', - ), - 'class' => 'autosubmit' + $this->addElement('text', 'object_name', array( + 'label' => $this->translate('Hostname'), + 'required' => true, + 'description' => $this->translate('Icinga object name for this host') )); - if ($isTemplate) { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Host template name'), - 'required' => true, - 'description' => $this->translate('Name for the Icinga host template you are going to create') - )); - } else { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Hostname'), - 'required' => true, - 'description' => $this->translate('Hostname for the Icinga host you are going to create') - )); - } - $this->addElement('text', 'address', array( 'label' => $this->translate('Host address'), 'description' => $this->translate('Host address. Usually an IPv4 address, but may be any kind of address your check plugin is able to deal with') @@ -45,95 +25,29 @@ class IcingaHostForm extends DirectorObjectForm 'description' => $this->translate('Usually your hosts main IPv6 address') )); - $this->addElement('select', 'check_command_id', array( - 'label' => $this->translate('Check command'), - 'description' => $this->translate('Check command definition') - )); - - $this->optionalBoolean( - 'enable_notifications', - $this->translate('Send notifications'), - $this->translate('Whether to send notifications for this host') - ); - - $this->optionalBoolean( - 'enable_active_checks', - $this->translate('Execute active checks'), - $this->translate('Whether to actively check this host') - ); - - $this->optionalBoolean( - 'enable_passive_checks', - $this->translate('Accept passive checks'), - $this->translate('Whether to accept passive check results for this host') - ); - - $this->optionalBoolean( - 'enable_event_handler', - $this->translate('Enable event handler'), - $this->translate('Whether to enable event handlers this host') - ); - - $this->optionalBoolean( - 'enable_perfdata', - $this->translate('Process performance data'), - $this->translate('Whether to process performance data provided by this host') - ); - - $this->optionalBoolean( - 'volatile', - $this->translate('Volatile'), - $this->translate('Whether this check is volatile.') - ); + $this->addImportsElement(); $this->addElement('text', 'groups', array( 'label' => $this->translate('Hostgroups'), 'description' => $this->translate('One or more comma separated hostgroup names') )); - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited host template names') - )); + if ($this->isTemplate()) { + $this->addElement('text', 'address', array( + 'label' => $this->translate('Host address'), + 'description' => $this->translate('Host address. Usually an IPv4 address, but may be any kind of address your check plugin is able to deal with') + )); - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this host in this specific Icinga cluster zone') - )); - } + $this->addElement('text', 'address6', array( + 'label' => $this->translate('IPv6 address'), + 'description' => $this->translate('Usually your hosts main IPv6 address') + )); - public function loadObject($id) - { - parent::loadObject($id); - - $this->addFields(); - - $this->moveSubmitToBottom(); - } - - public function addFields() - { - $fields = $this->getObject()->getFields($this); - $vars = $this->getObject()->vars(); - - foreach ($fields as $field) { - $datatype = new $field->datatype; - $datafield = DirectorDatafield::load($field->datafield_id, $this->getDb()); - $datatype->setSettings($datafield->getSettings()); - $varname = $datafield->varname; - $el = $datatype->getFormElement('var_' . $varname, $this); - $el->setLabel($field->caption); - $el->setDescription($field->description); - if (isset($vars->$varname)) { - $el->setValue($vars->{$varname}->getValue()); - } - - if ($field->is_required === 'y') - { - $el->setRequired(true); - } - - $this->addElement($el); + $this->addCheckCommandElement()->addCheckFlagElements(); + } else { + $this->getElement('imports')->setRequired(); } + + $this->addZoneElement(); } } diff --git a/application/forms/IcingaHostGroupForm.php b/application/forms/IcingaHostGroupForm.php index 59acf50c..31c309c9 100644 --- a/application/forms/IcingaHostGroupForm.php +++ b/application/forms/IcingaHostGroupForm.php @@ -8,39 +8,15 @@ class IcingaHostGroupForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; - $this->addElement('select', 'object_type', array( - 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), - 'multiOptions' => array( - null => '- please choose -', - 'object' => 'Hostgroup object', - 'template' => 'Hostgroup template', - ) + $this->addElement('text', 'object_name', array( + 'label' => $this->translate('Hostgroup'), + 'required' => true, + 'description' => $this->translate('Icinga object name for this hostgroup') )); - if ($isTemplate) { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Hostgroup template name'), - 'required' => true, - 'description' => $this->translate('Hostgroup for the Icinga hostgroup template you are going to create') - )); - } else { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Hostgroup'), - 'required' => true, - 'description' => $this->translate('Hostgroup for the Icinga hostgroup you are going to create') - )); - } - $this->addElement('text', 'display_name', array( 'label' => $this->translate('Display Name'), 'description' => $this->translate('The name which should displayed.') )); - - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited hostgroup template names') - )); } } diff --git a/application/forms/IcingaHostVarForm.php b/application/forms/IcingaHostVarForm.php index 3fe0a70d..cb15bcb0 100644 --- a/application/forms/IcingaHostVarForm.php +++ b/application/forms/IcingaHostVarForm.php @@ -12,23 +12,24 @@ class IcingaHostVarForm extends DirectorObjectForm public function setup() { $this->addElement('select', 'host_id', array( - 'label' => $this->translate('Host'), - 'description' => $this->translate('The name of the host'), - 'required' => true + 'label' => $this->translate('Host'), + 'description' => $this->translate('The name of the host'), + 'multiOptions' => $this->optionalEnum($this->db->enumHosts()), + 'required' => true )); $this->addElement('text', 'varname', array( - 'label' => $this->translate('Name'), + 'label' => $this->translate('Name'), 'description' => $this->translate('host var name') )); $this->addElement('textarea', 'varvalue', array( - 'label' => $this->translate('Value'), + 'label' => $this->translate('Value'), 'description' => $this->translate('host var value') )); $this->addElement('text', 'format', array( - 'label' => $this->translate('Format'), + 'label' => $this->translate('Format'), 'description' => $this->translate('value format') )); } diff --git a/application/forms/IcingaServiceFieldForm.php b/application/forms/IcingaServiceFieldForm.php index 49c506a9..202b4fd7 100644 --- a/application/forms/IcingaServiceFieldForm.php +++ b/application/forms/IcingaServiceFieldForm.php @@ -9,21 +9,20 @@ class IcingaServiceFieldForm extends DirectorObjectForm public function setup() { $this->addElement('select', 'service_id', array( - 'label' => 'Service Tpl', - 'description' => 'Service Template', - 'multiOptions' => $this->optionalEnum($this->getDb()->enumServiceTemplates()) + 'label' => 'Service template', + 'multiOptions' => $this->optionalEnum($this->db->enumServiceTemplates()) )); $this->addElement('select', 'datafield_id', array( - 'label' => 'Field', - 'description' => 'Field to assign', - 'multiOptions' => $this->optionalEnum($this->getDb()->enumDatafields()) + 'label' => 'Field', + 'description' => 'Field to assign', + 'multiOptions' => $this->optionalEnum($this->db->enumDatafields()) )); $this->optionalBoolean( 'is_required', $this->translate('Required'), - $this->translate('Whether this filed is required or not.') + $this->translate('Whether this field should be required or not') ); } } diff --git a/application/forms/IcingaServiceForm.php b/application/forms/IcingaServiceForm.php index 2a37227b..dd4cb533 100644 --- a/application/forms/IcingaServiceForm.php +++ b/application/forms/IcingaServiceForm.php @@ -34,60 +34,13 @@ class IcingaServiceForm extends DirectorObjectForm )); } - $this->addElement('select', 'check_command_id', array( - 'label' => $this->translate('Check command'), - 'description' => $this->translate('Check command definition') - )); - - $this->optionalBoolean( - 'enable_notifications', - $this->translate('Send notifications'), - $this->translate('Whether to send notifications for this service') - ); - - $this->optionalBoolean( - 'enable_active_checks', - $this->translate('Execute active checks'), - $this->translate('Whether to actively check this service') - ); - - $this->optionalBoolean( - 'enable_passive_checks', - $this->translate('Accept passive checks'), - $this->translate('Whether to accept passive check results for this service') - ); - - $this->optionalBoolean( - 'enable_event_handler', - $this->translate('Enable event handler'), - $this->translate('Whether to enable event handlers this service') - ); - - $this->optionalBoolean( - 'enable_perfdata', - $this->translate('Process performance data'), - $this->translate('Whether to process performance data provided by this service') - ); - - $this->optionalBoolean( - 'volatile', - $this->translate('Volatile'), - $this->translate('Whether this check is volatile.') - ); - - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this host in this specific Icinga cluster zone') - )); - $this->addElement('text', 'groups', array( 'label' => $this->translate('Servicegroups'), 'description' => $this->translate('One or more comma separated servicegroup names') )); - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited service template names') - )); + $this->addCheckCommandElement() + ->addCheckFlagElements() + ->addImportsElement(); } } diff --git a/application/forms/IcingaServiceGroupForm.php b/application/forms/IcingaServiceGroupForm.php index 6829d16c..9ec7e02c 100644 --- a/application/forms/IcingaServiceGroupForm.php +++ b/application/forms/IcingaServiceGroupForm.php @@ -8,39 +8,15 @@ class IcingaServiceGroupForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; - $this->addElement('select', 'object_type', array( - 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), - 'multiOptions' => array( - null => '- please choose -', - 'object' => 'Servicegroup object', - 'template' => 'Servicegroup template', - ) + $this->addElement('text', 'object_name', array( + 'label' => $this->translate('Servicegroup'), + 'required' => true, + 'description' => $this->translate('Icinga object name for this servicegroup') )); - if ($isTemplate) { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Servicegroup template name'), - 'required' => true, - 'description' => $this->translate('Servicegroup for the Icinga servicegroup template you are going to create') - )); - } else { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Servicegroup'), - 'required' => true, - 'description' => $this->translate('Servicegroup for the Icinga servicegroup you are going to create') - )); - } - $this->addElement('text', 'display_name', array( 'label' => $this->translate('Display Name'), 'description' => $this->translate('The name which should displayed.') )); - - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited servicegroup template names') - )); } } diff --git a/application/forms/IcingaServiceVarForm.php b/application/forms/IcingaServiceVarForm.php index e0fcb74d..e7ac4a07 100644 --- a/application/forms/IcingaServiceVarForm.php +++ b/application/forms/IcingaServiceVarForm.php @@ -12,23 +12,24 @@ class IcingaServiceVarForm extends DirectorObjectForm public function setup() { $this->addElement('select', 'service_id', array( - 'label' => $this->translate('Service'), - 'description' => $this->translate('The name of the service'), - 'required' => true + 'label' => $this->translate('Service'), + 'description' => $this->translate('The name of the service'), + 'multiOptions' => $this->optionalEnum($this->db->enumServices()), + 'required' => true )); $this->addElement('text', 'varname', array( - 'label' => $this->translate('Name'), + 'label' => $this->translate('Name'), 'description' => $this->translate('service var name') )); $this->addElement('textarea', 'varvalue', array( - 'label' => $this->translate('Value'), + 'label' => $this->translate('Value'), 'description' => $this->translate('service var value') )); $this->addElement('text', 'format', array( - 'label' => $this->translate('Format'), + 'label' => $this->translate('Format'), 'description' => $this->translate('value format') )); } diff --git a/application/forms/IcingaTimePeriodForm.php b/application/forms/IcingaTimePeriodForm.php index 2470f250..51a2de5f 100644 --- a/application/forms/IcingaTimePeriodForm.php +++ b/application/forms/IcingaTimePeriodForm.php @@ -43,15 +43,7 @@ class IcingaTimePeriodForm extends DirectorObjectForm 'description' => $this->translate('the update method'), )); - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this host in this specific Icinga cluster zone'), - 'required' => true - )); - - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited timperiods template names') - )); + $this->addZoneElement(); + $this->addImportsElement(); } } diff --git a/application/forms/IcingaUserForm.php b/application/forms/IcingaUserForm.php index b94bcf1a..133c3ca5 100644 --- a/application/forms/IcingaUserForm.php +++ b/application/forms/IcingaUserForm.php @@ -49,20 +49,11 @@ class IcingaUserForm extends DirectorObjectForm $this->translate('Whether to send notifications for this user') ); - - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this user in this specific Icinga cluster zone') - )); - $this->addElement('text', 'groups', array( 'label' => $this->translate('Usergroups'), 'description' => $this->translate('One or more comma separated usergroup names') )); - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited user template names') - )); + $this->addImportsElement(); } } diff --git a/application/forms/IcingaUserGroupForm.php b/application/forms/IcingaUserGroupForm.php index ff1b15c8..aa1a7faa 100644 --- a/application/forms/IcingaUserGroupForm.php +++ b/application/forms/IcingaUserGroupForm.php @@ -8,44 +8,15 @@ class IcingaUserGroupForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; - $this->addElement('select', 'object_type', array( - 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), - 'multiOptions' => array( - null => '- please choose -', - 'object' => 'Usergroup object', - 'template' => 'Usergroup template', - ) + $this->addElement('text', 'object_name', array( + 'label' => $this->translate('Usergroup'), + 'required' => true, + 'description' => $this->translate('Icinga object name for this usergroup') )); - if ($isTemplate) { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Usergroup template name'), - 'required' => true, - 'description' => $this->translate('Usergroup for the Icinga usergroup template you are going to create') - )); - } else { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Usergroup'), - 'required' => true, - 'description' => $this->translate('Usergroup for the Icinga usergroup you are going to create') - )); - } - $this->addElement('text', 'display_name', array( 'label' => $this->translate('Display Name'), 'description' => $this->translate('The name which should displayed.') )); - - $this->addElement('select', 'zone_id', array( - 'label' => $this->translate('Cluster Zone'), - 'description' => $this->translate('Check this usergroup in this specific Icinga cluster zone') - )); - - $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), - 'description' => $this->translate('The inherited usergroup template names') - )); } } diff --git a/application/forms/IcingaZoneForm.php b/application/forms/IcingaZoneForm.php index 27c8219b..1705423c 100644 --- a/application/forms/IcingaZoneForm.php +++ b/application/forms/IcingaZoneForm.php @@ -10,7 +10,7 @@ class IcingaZoneForm extends DirectorObjectForm { $this->addElement('select', 'object_type', array( 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), + 'description' => $this->translate('Whether this should be a template'), 'multiOptions' => $this->optionalEnum(array( 'object' => $this->translate('Zone object'), 'template' => $this->translate('Zone template'), @@ -24,22 +24,23 @@ class IcingaZoneForm extends DirectorObjectForm )); $this->addElement('select', 'is_global', array( - 'label' => 'Global zone', - 'description' => 'Whether this zone should be available everywhere', + 'label' => 'Global zone', + 'description' => 'Whether this zone should be available everywhere', 'multiOptions' => array( 'n' => $this->translate('No'), 'y' => $this->translate('Yes'), ), - 'required' => true, + 'required' => true, )); $this->addElement('select', 'parent_zone_id', array( - 'label' => $this->translate('Parent Zone'), - 'description' => $this->translate('Chose an (optional) parent zone') + 'label' => $this->translate('Parent Zone'), + 'description' => $this->translate('Chose an (optional) parent zone'), + 'multiOptions' => $this->optionalEnum($this->db->enumZones()) )); $this->addElement('text', 'imports', array( - 'label' => $this->translate('Imports'), + 'label' => $this->translate('Imports'), 'description' => $this->translate('The inherited zone template names') )); } From 3d205724c39a569fda0ccebb9587f9c0503370d4 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:39:00 +0200 Subject: [PATCH 37/92] IcingaObject: resolving methods should be generic --- library/Director/Objects/IcingaObject.php | 110 +++++++++++++++++++--- 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index 09620d42..99eed143 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -139,37 +139,119 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->importedObjects; } + public function clearImportedObjects() + { + $this->importedObjects = null; + return $this; + } + public function getResolvedProperties() { - $res = $this->resolveProperties(); - return $res['_MERGED_']; + return $this->getResolved('Properties'); + } + + public function getInheritedProperties() + { + return $this->getInherited('Properties'); } public function resolveProperties() { - $props = array(); - $props['_MERGED_'] = (object) array(); - $objects = $this->importedObjects(); + return $this->resolve('Properties'); + } + public function getResolvedFields() + { + return $this->getResolved('Fields'); + } + + public function getInheritedFields() + { + return $this->getInherited('Fields'); + } + + public function resolveFields() + { + return $this->resolve('Fields'); + } + + public function getResolvedVars() + { + return $this->getResolved('Vars'); + } + + public function getInheritedVars() + { + return $this->getInherited('Vars'); + } + + public function resolveVars() + { + return $this->resolve('Vars'); + } + + public function getVars() + { + $vars = (object) array(); + foreach ($this->vars() as $key => $var) { + $vars->$key = $var->getValue(); + } + + return $vars; + } + + protected function getResolved($what) + { + $func = 'resolve' . $what; + $res = $this->$func(); + return $res['_MERGED_']; + } + + protected function getInherited($what) + { + $func = 'resolve' . $what; + $res = $this->$func(); + return $res['_INHERITED_']; + } + + protected function resolve($what) + { + $vals = array(); + $vals['_MERGED_'] = (object) array(); + $vals['_INHERITED_'] = (object) array(); + $objects = $this->importedObjects(); $objects[$this->object_name] = $this; - $blacklist = array('id', 'object_type', 'object_name'); + + $get = 'get' . $what; + $getResolved = 'getResolved' . $what; + + if ($what === 'Properties') { + $blacklist = array('id', 'object_type', 'object_name'); + } else { + $blacklist = array(); + } + foreach ($objects as $name => $object) { - $props[$name] = (object) array(); - if ($name === $this->object_name) { - $pprops = $object->getProperties(); + $vals[$name] = (object) array(); + + if ($name === $this->object_name || $this->object_name === null) { + $pvals = $object->$get(); } else { - $pprops = $object->getResolvedProperties(); + $pvals = $object->$getResolved(); } - foreach ($pprops as $key => $value) { + foreach ($pvals as $key => $value) { if (in_array($key, $blacklist)) continue; if ($value !== null) { - $props[$name]->$key = $value; - $props['_MERGED_']->$key = $value; + $vals[$name]->$key = $value; + $vals['_MERGED_']->$key = $value; + if ($name !== $this->object_name) { + $vals['_INHERITED_']->$key = $value; + } } } } - return $props; + return $vals; } protected function assertCustomVarsSupport() From 87ddaf19d8b739a1aa6ea6eb2bbc2ae6964901a8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:40:13 +0200 Subject: [PATCH 38/92] welcome: first attempts to make it look better --- application/views/scripts/welcome/index.phtml | 22 ++++++++++++++++++- configuration.php | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/application/views/scripts/welcome/index.phtml b/application/views/scripts/welcome/index.phtml index c89dd824..ac658467 100644 --- a/application/views/scripts/welcome/index.phtml +++ b/application/views/scripts/welcome/index.phtml @@ -7,5 +7,25 @@ errorMessage): ?>

errorMessage ?>

-Nothing to see here yet. We will point you to the most common tasks later on. +translate('Monitoring Nodes'), 'director/commands'), + array('host', $this->translate('Host objecs'), 'director/hosts'), + array('services', $this->translate('Monitored Services'), 'director/services'), + array('users', $this->translate('Users / Contacts'), 'director/users'), + array('chat', $this->translate('Alarms and notifications'), 'director/notificatios'), + array('database', $this->translate('Sync / Import'), 'director/list/importsource'), + array('wrench', $this->translate('Configuration'), 'director/list/generatedconfig'), +); +?> +
diff --git a/configuration.php b/configuration.php index 54f1a736..4ca0e9c8 100644 --- a/configuration.php +++ b/configuration.php @@ -25,6 +25,7 @@ $section = $this->menuSection( $this->translate('Icinga Director') )->setIcon('cubes'); +$section->add($this->translate('Overview'))->setUrl('director/welcome')->setPriority(20); $section->add($this->translate('Global'))->setUrl('director/commands'); $section->add($this->translate('Hosts'))->setUrl('director/hosts'); $section->add($this->translate('Fields'))->setUrl('director/field/host')->setPriority(903); From 6187777d084dd4799bc118b9e520aa3d412f766c Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:40:49 +0200 Subject: [PATCH 39/92] css/module.less: CSS related to previous commit --- public/css/module.less | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/public/css/module.less b/public/css/module.less index 7eed1405..dfbcf526 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -1,3 +1,41 @@ + +ul.main-actions { + margin: 0; + li { + list-style-type: none; + width: 20em; + height: 20em; + text-align: center; + display: block; + padding: 0; + float: left; + + a { + i { + width: 100%; + height: 1.3em; + font-size: 8em; + display: inline-block; + line-height: 1em; + } + + border: 1px solid #666; + padding: 1em; + margin: 0.5em; + font-size: 1.1em; + color: #666; + font-weight: bold; + display: block; + + &:hover { + background-color: #666; + color: white; + text-decoration: none; + } + } + } +} + /* BEGIN Forms */ form dt label { width: auto; From 2643b6ae8cc6cd65e94e51a4cd90f3a02e6d5092 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:43:33 +0200 Subject: [PATCH 40/92] DirectorObjectForm: improve import handling --- .../Director/Web/Form/DirectorObjectForm.php | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 1cc9a1df..215e2a72 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -116,10 +116,16 @@ abstract class DirectorObjectForm extends QuickForm if ($object->supportsImports()) { if (array_key_exists('imports', $values)) { - $object->imports()->set( - preg_split('/\s*,\s*/', $values['imports'], -1, PREG_SPLIT_NO_EMPTY) - ); + $value = $values['imports']; + + // TODO: Compat for comma separated string, check if still needed + if (! is_array($value)) { + $value = preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); + } + + $object->imports()->set($value); $handled['imports'] = true; + $object->clearImportedObjects(); } } @@ -268,10 +274,12 @@ abstract class DirectorObjectForm extends QuickForm ); } - if ($this->object->supportsImports()) { - $this->getElement('imports')->setValue( - implode(', ', $this->object->imports()->listImportNames()) - ); + if ($object->supportsImports()) { + $el = $this->getElement('imports'); + if ($el) { + $el->setMultiOptions($this->enumAllowedTemplates()); + $el->setValue($object->imports()->listImportNames()); + } } if ($this->object->supportsCustomVars()) { From a61ab0f890d4e6de0e8c6063f077fd3dd763db46 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:44:03 +0200 Subject: [PATCH 41/92] HosttemplatesController: first templates controller --- application/controllers/HosttemplatesController.php | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 application/controllers/HosttemplatesController.php diff --git a/application/controllers/HosttemplatesController.php b/application/controllers/HosttemplatesController.php new file mode 100644 index 00000000..49b15307 --- /dev/null +++ b/application/controllers/HosttemplatesController.php @@ -0,0 +1,7 @@ + Date: Thu, 30 Jul 2015 11:45:55 +0200 Subject: [PATCH 42/92] IcingaHost: use inherited fields support --- library/Director/Objects/IcingaHost.php | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/library/Director/Objects/IcingaHost.php b/library/Director/Objects/IcingaHost.php index 7462776c..1c918573 100644 --- a/library/Director/Objects/IcingaHost.php +++ b/library/Director/Objects/IcingaHost.php @@ -43,6 +43,8 @@ class IcingaHost extends IcingaObject protected $supportsImports = true; + protected $supportsFields = true; + protected function renderCheck_command_id() { return $this->renderCommandProperty($this->check_command_id); @@ -82,22 +84,4 @@ class IcingaHost extends IcingaObject { return $this->renderBooleanProperty('volatile'); } - - public function getFields(DirectorObjectForm $form) - { - $db = $this->getDb(); - - $query = $db->select() - ->from( - array('df' => 'director_datafield') - ) - ->join( - array('hf' => 'icinga_host_field'), - 'df.id = hf.datafield_id' - ) - ->where('hf.host_id = ?', (int) $this->id) - ->order('df.caption ASC'); - - return $db->fetchAll($query); - } } From a88563f9254be655d6d4d14169daf66cab432b24 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:46:27 +0200 Subject: [PATCH 43/92] DirectorActivityLog: start to log related objects First implementation: groups --- library/Director/Objects/DirectorActivityLog.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/Director/Objects/DirectorActivityLog.php b/library/Director/Objects/DirectorActivityLog.php index 1ff183cc..3da05baf 100644 --- a/library/Director/Objects/DirectorActivityLog.php +++ b/library/Director/Objects/DirectorActivityLog.php @@ -39,6 +39,19 @@ class DirectorActivityLog extends DbObject } } + protected static function prepareNewObjectProperties(DbObject $object) + { + $props = $object->getProperties(); + if ($object->supportsCustomVars()) { + // $props->vars = $object->vars()->toJson(); + } + if ($object->supportsGroups()) { + $props['groups'] = $object->groups()->listGroupNames(); + } + + return json_encode($props); + } + public static function logCreation(DbObject $object, Db $db) { $data = array( @@ -46,7 +59,7 @@ class DirectorActivityLog extends DbObject 'action_name' => 'create', 'author' => self::username(), 'object_type' => $object->getTableName(), - 'new_properties' => json_encode($object->getProperties()), + 'new_properties' => self::prepareNewObjectProperties($object), 'change_time' => date('Y-m-d H:i:s'), // TODO -> postgres! 'parent_checksum' => $db->getLastActivityChecksum() ); From 5ab69a48767533ac1f2a25e3b35126e0d8be9d56 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:47:46 +0200 Subject: [PATCH 44/92] DirectorObjectForm: just spaces for obsolete tests --- library/Director/Web/Form/DirectorObjectForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 215e2a72..c4089c64 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -131,9 +131,9 @@ abstract class DirectorObjectForm extends QuickForm if ($object->supportsRanges()) { $object->ranges()->set(array( - 'monday' => 'eins', + 'monday' => 'eins', 'tuesday' => '00:00-24:00', - 'sunday' => 'zwei', + 'sunday' => 'zwei', )); } From db54a4f365e285c994344330043b4c664586435c Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:48:12 +0200 Subject: [PATCH 45/92] DirectorObjectForm: one more string to translate --- library/Director/Web/Form/DirectorObjectForm.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index c4089c64..e4341fc5 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -471,6 +471,7 @@ abstract class DirectorObjectForm extends QuickForm $this->translate('Service'); $this->translate('Zone'); $this->translate('Command'); + $this->translate('User'); // ... TBC } } From eb1d4c67b01ceccb74829ac321cbaf17a5733fc4 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:48:42 +0200 Subject: [PATCH 46/92] DirectorObjectForm: finally remove obsolete helpers --- .../Director/Web/Form/DirectorObjectForm.php | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index e4341fc5..72fc78e6 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -333,46 +333,6 @@ abstract class DirectorObjectForm extends QuickForm if ($this->object !== null) { $this->object->setConnection($db); } - if ($this->hasElement('parent_zone_id')) { - $this->getElement('parent_zone_id') - ->setMultiOptions($this->optionalEnum($db->enumZones())); - } - if ($this->hasElement('host_id')) { - $this->getElement('host_id') - ->setMultiOptions($this->optionalEnum($db->enumHosts())); - } - if ($this->hasElement('hostgroup_id')) { - $this->getElement('hostgroup_id') - ->setMultiOptions($this->optionalEnum($db->enumHostgroups())); - } - if ($this->hasElement('service_id')) { - $this->getElement('service_id') - ->setMultiOptions($this->optionalEnum($db->enumServices())); - } - if ($this->hasElement('servicegroup_id')) { - $this->getElement('servicegroup_id') - ->setMultiOptions($this->optionalEnum($db->enumServicegroups())); - } - if ($this->hasElement('user_id')) { - $this->getElement('user_id') - ->setMultiOptions($this->optionalEnum($db->enumUsers())); - } - if ($this->hasElement('usergroup_id')) { - $this->getElement('usergroup_id') - ->setMultiOptions($this->optionalEnum($db->enumUsergroups())); - } - if ($this->hasElement('zone_id')) { - $this->getElement('zone_id') - ->setMultiOptions($this->optionalEnum($db->enumZones())); - } - if ($this->hasElement('check_command_id')) { - $this->getElement('check_command_id') - ->setMultiOptions($this->optionalEnum($db->enumCheckCommands())); - } - if ($this->hasElement('command_id')) { - $this->getElement('command_id') - ->setMultiOptions($this->optionalEnum($db->enumCommands())); - } return $this; } From 7ebb2dcdc950feb9be744b19acd81e4d8346a7a7 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:49:08 +0200 Subject: [PATCH 47/92] QuickForm: add onRequest hook --- library/Director/Web/Form/QuickForm.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index dcecf4c6..c13ff315 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -338,10 +338,21 @@ abstract class QuickForm extends Zend_Form Icinga::app()->getFrontController()->getResponse()->redirectAndExit($url); } + protected function onRequest() + { + } + + public function setRequest(Request $request) + { + $this->request = $request; + $this->onRequest(); + return $this; + } + public function getRequest() { if ($this->request === null) { - $this->request = Icinga::app()->getFrontController()->getRequest(); + $this->setRequest(Icinga::app()->getFrontController()->getRequest()); } return $this->request; } From 8c96af234875c4970f828e7dccab2a667e400043 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 11:51:45 +0200 Subject: [PATCH 48/92] DirectorObjectForm: postpone element creation We must first load the object to have it available when creating our form elements --- library/Director/Web/Form/DirectorObjectForm.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 72fc78e6..4d801eb9 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -249,7 +249,6 @@ abstract class DirectorObjectForm extends QuickForm public function loadObject($id) { - $this->prepareElements(); $class = $this->getObjectClassname(); $object = $this->object = $class::load($id, $this->db); if ($object instanceof IcingaObject) { @@ -259,8 +258,11 @@ abstract class DirectorObjectForm extends QuickForm if (! is_array($id)) { $this->addHidden('id'); } - $this->setDefaults($this->object->getProperties()); - if (! $this->object instanceof IcingaObject) { + $this->prepareElements(); + + $props = $object->getProperties(); + if (! $object instanceof IcingaObject) { + $this->setDefaults($props); return $this; } From 63a5e3fb77b672f87dc0b908dd1ac3207e84b65a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:41:48 +0200 Subject: [PATCH 49/92] DirectorObjectForm: add missing use statement --- library/Director/Web/Form/DirectorObjectForm.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 4d801eb9..e7a429cc 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -3,6 +3,7 @@ namespace Icinga\Module\Director\Web\Form; use Icinga\Module\Director\Objects\IcingaObject; +use Zend_Form_Element_Select as Zf_Select; abstract class DirectorObjectForm extends QuickForm { From 364904e8e7853a4babf7f2e71f535f7cb32dab39 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:44:40 +0200 Subject: [PATCH 50/92] DirectorObjectForm: less references --- library/Director/Web/Form/DirectorObjectForm.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index e7a429cc..e3562350 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -86,7 +86,8 @@ abstract class DirectorObjectForm extends QuickForm } } - if ($this->object->supportsCustomVars()) { + if ($object->supportsCustomVars()) { + $vars = array(); $newvar = array( 'type' => 'string', @@ -271,9 +272,9 @@ abstract class DirectorObjectForm extends QuickForm $this->removeElement('submit'); } - if ($this->object->supportsGroups()) { + if ($object->supportsGroups()) { $this->getElement('groups')->setValue( - implode(', ', $this->object->groups()->listGroupNames()) + implode(', ', $object->groups()->listGroupNames()) ); } @@ -285,13 +286,13 @@ abstract class DirectorObjectForm extends QuickForm } } - if ($this->object->supportsCustomVars()) { + if ($object->supportsFields() && ! $object->isTemplate()) { foreach ($this->object->vars() as $key => $value) { $this->addCustomVar($key, $value); } } - if ($this->object->supportsRanges()) { + if ($object->supportsRanges()) { /* TODO implement when new logic for customvars is there foreach ($this->object->ranges()->getRanges() as $key => $value) { $this->addRange($key, $value); From 9d4bd323a8e1075eb7f6651534f35d2f26ec81f6 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:46:08 +0200 Subject: [PATCH 51/92] DirectorObjectForm: methods dealing with fields --- .../Director/Web/Form/DirectorObjectForm.php | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index e3562350..cb0a51f0 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -3,6 +3,7 @@ namespace Icinga\Module\Director\Web\Form; use Icinga\Module\Director\Objects\IcingaObject; +use Icinga\Module\Director\Objects\DirectorDatafield; use Zend_Form_Element_Select as Zf_Select; abstract class DirectorObjectForm extends QuickForm @@ -150,6 +151,44 @@ abstract class DirectorObjectForm extends QuickForm return $this; } + public function addFields() + { + $object = $this->object(); + $fields = $object->getResolvedFields(); + $vars = $object->vars(); + + foreach ($fields as $field) { + $varname = $field->varname; + if (isset($vars->$varname)) { + $value = $vars->{$varname}->getValue(); + } else { + $value = null; + } +$inherited = null; // Just testing + $this->addField($field, $value, $inherited); + } + } + + protected function addField($field, $value = null, $inherited = null) + { + $datafield = DirectorDatafield::load($field->datafield_id, $this->getDb()); + $datatype = new $datafield->datatype; + $datatype->setSettings($datafield->getSettings()); + + $name = 'var_' . $datafield->varname; + $el = $datatype->getFormElement($name, $this); + + $el->setLabel($datafield->caption); + $el->setDescription($datafield->description); + + if ($field->is_required === 'y') { + $el->setRequired(true); + } + + $this->addElement($el); + $this->setElementValue($name, $value, $inherited); + } + protected function setElementValue($name, $value = null, $inherited = null) { $el = $this->getElement($name); From 49042393bffa276139829fab31815986b843deb5 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:52:38 +0200 Subject: [PATCH 52/92] DirectorObjectForm: use helper method for button --- library/Director/Web/Form/DirectorObjectForm.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index cb0a51f0..4c967130 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -307,8 +307,6 @@ $inherited = null; // Just testing return $this; } - if ($submit = $this->getElement('submit')) { - $this->removeElement('submit'); } if ($object->supportsGroups()) { @@ -339,9 +337,7 @@ $inherited = null; // Just testing */ } - if ($submit) { - $this->addElement($submit); - } + $this->moveSubmitToBottom(); if (! $this->hasBeenSubmitted()) { $this->beforeValidation($this->object->getProperties()); From 8b9a212bf7ed243a36fe47cf7147df6532d56332 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:53:37 +0200 Subject: [PATCH 53/92] DirectorObjectForm: experiments with inheritance --- library/Director/Web/Form/DirectorObjectForm.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 4c967130..a1a5d961 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -307,6 +307,11 @@ $inherited = null; // Just testing return $this; } + $inherited = $this->object->getInheritedProperties(); + + foreach ($props as $k => $v) { + $i = property_exists($inherited, $k) ? $inherited->$k : null; + $this->setElementValue($k, $v, $i); } if ($object->supportsGroups()) { From 10d2d513dfdfb2d8ecefd63640a4e393cccebe57 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 12:54:54 +0200 Subject: [PATCH 54/92] DirectorObjectForm: remove (probably) useless hook --- library/Director/Web/Form/DirectorObjectForm.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index a1a5d961..ef402e40 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -344,9 +344,6 @@ $inherited = null; // Just testing $this->moveSubmitToBottom(); - if (! $this->hasBeenSubmitted()) { - $this->beforeValidation($this->object->getProperties()); - } return $this; } From dc91ab498d32ced1c6e136df5729f1d538fcb5cc Mon Sep 17 00:00:00 2001 From: Alexander Fuhr Date: Thu, 30 Jul 2015 14:08:08 +0200 Subject: [PATCH 55/92] PostgreSQL Schema: Update it to the last MySQL state fixes #9783 --- schema/pgsql-changes/upgrade_24-34.sql | 189 +++++++++++++++++++++++ schema/pgsql.sql | 198 +++++++++++++++++++++++-- 2 files changed, 376 insertions(+), 11 deletions(-) create mode 100644 schema/pgsql-changes/upgrade_24-34.sql diff --git a/schema/pgsql-changes/upgrade_24-34.sql b/schema/pgsql-changes/upgrade_24-34.sql new file mode 100644 index 00000000..6aed5e72 --- /dev/null +++ b/schema/pgsql-changes/upgrade_24-34.sql @@ -0,0 +1,189 @@ +ALTER TABLE director_generated_file ALTER COLUMN content SET DEFAULT NULL; +ALTER TABLE icinga_host_field ALTER COLUMN is_required SET DEFAULT NOT NULL; +ALTER TABLE icinga_service_field ALTER COLUMN is_required SET DEFAULT NOT NULL; + +CREATE TABLE import_source ( + id serial, + source_name character varying(64) NOT NULL, + key_column character varying(64) NOT NULL, + provider_class character varying(72) NOT NULL, + PRIMARY KEY (id) +); + +CREATE INDEX import_source_search_idx ON import_source (key_column); + + +CREATE TABLE import_source_setting ( + source_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text NOT NULL, + PRIMARY KEY (source_id, setting_name), + CONSTRAINT import_source_settings_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE CASCADE + ON UPDATE CASCADE +); + +CREATE INDEX import_source_setting_source ON import_source_setting (source_id); + + +CREATE TABLE imported_rowset ( + checksum bytea CHECK(LENGTH(checksum) = 20), + PRIMARY KEY (checksum) +); + + +CREATE TABLE import_run ( + id serial, + source_id integer NOT NULL, + rowset_checksum bytea CHECK(LENGTH(rowset_checksum) = 20), + start_time timestamp with time zone NOT NULL, + end_time timestamp with time zone NOT NULL, + succeeded enum_boolean DEFAULT NULL, + PRIMARY KEY (id), + CONSTRAINT import_run_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + CONSTRAINT import_run_rowset + FOREIGN KEY (rowset_checksum) + REFERENCES imported_rowset (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX import_run_import_source ON import_run (source_id); +CREATE INDEX import_run_rowset ON import_run (rowset_checksum); + + +CREATE TABLE imported_row ( + checksum bytea CHECK(LENGTH(checksum) = 20), + object_name character varying(255) NOT NULL, + PRIMARY KEY (checksum) +); + +COMMENT ON COLUMN imported_row.checksum IS 'sha1(object_name;property_checksum;...)'; + + +CREATE TABLE imported_rowset_row ( + rowset_checksum bytea CHECK(LENGTH(checksum) = 20), + row_checksum bytea CHECK(LENGTH(checksum) = 20), + PRIMARY KEY (rowset_checksum, row_checksum), + CONSTRAINT imported_rowset_row_rowset + FOREIGN KEY (rowset_checksum) + REFERENCES imported_rowset (checksum) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT imported_rowset_row_row + FOREIGN KEY (row_checksum) + REFERENCES imported_row (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX imported_rowset_row_rowset_checksum ON imported_rowset_row (rowset_checksum); +CREATE INDEX imported_rowset_row_row_checksum ON imported_rowset_row (row_checksum); + +CREATE TABLE imported_property ( + checksum bytea CHECK(LENGTH(checksum) = 20), + property_name character varying(64) NOT NULL, + property_value text NOT NULL, + format enum_property_format, + PRIMARY KEY (checksum) +); + +CREATE INDEX imported_property_search_idx ON imported_property (property_name); + +CREATE TABLE imported_row_property ( + row_checksum bytea CHECK(LENGTH(row_checksum) = 20), + property_checksum bytea CHECK(LENGTH(property_checksum) = 20), + PRIMARY KEY (row_checksum, property_checksum), + CONSTRAINT imported_row_property_row + FOREIGN KEY (row_checksum) + REFERENCES imported_row (checksum) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT imported_row_property_property + FOREIGN KEY (property_checksum) + REFERENCES imported_property (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX imported_row_property_row_checksum ON imported_row_property (row_checksum); +CREATE INDEX imported_row_property_property_checksum ON imported_row_property (property_checksum); + + +CREATE TYPE enum_sync_rule_object_type AS ENUM('host', 'user'); +CREATE TYPE enum_sync_rule_update_policy AS ENUM('merge', 'override', 'ignore'); + +CREATE TABLE sync_rule ( + id serial, + rule_name character varying(255) NOT NULL, + object_type enum_sync_rule_object_type NOT NULL, + update_policy enum_sync_rule_update_policy NOT NULL, + purge_existing enum_boolean NOT NULL DEFAULT 'n', + filter_expression text DEFAULT NULL, + PRIMARY KEY (id) +); + + +CREATE TYPE enum_sync_property_merge_policy AS ENUM('override', 'merge'); + +CREATE TABLE sync_property ( + id serial, + rule_id integer NOT NULL, + source_id integer NOT NULL, + source_expression character varying(255) NOT NULL, + destination_field character varying(64), + priority smallint NOT NULL, + filter_expression text DEFAULT NULL, + merge_policy enum_sync_property_merge_policy NOT NULL, + PRIMARY KEY (id), + CONSTRAINT sync_property_rule + FOREIGN KEY (rule_id) + REFERENCES sync_rule (id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT sync_property_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX sync_property_rule ON sync_property (rule_id); +CREATE INDEX sync_property_source ON sync_property (source_id); + + +CREATE TABLE import_row_modifier ( + id serial, + property_id integer NOT NULL, + provider_class character varying(72) NOT NULL, + PRIMARY KEY (id) +); + + +CREATE TABLE import_row_modifier_setting ( + modifier_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text DEFAULT NULL, + PRIMARY KEY (modifier_id) +); + + +CREATE TABLE director_datafield_setting ( + datafield_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text NOT NULL, + PRIMARY KEY (datafield_id, setting_name), + CONSTRAINT datafield_id_settings + FOREIGN KEY (datafield_id) + REFERENCES director_datafield (id) + ON DELETE CASCADE + ON UPDATE CASCADE +); + +CREATE INDEX director_datafield_datafield ON director_datafield_setting (datafield_id); diff --git a/schema/pgsql.sql b/schema/pgsql.sql index 8dd92bf8..aa09ddb0 100644 --- a/schema/pgsql.sql +++ b/schema/pgsql.sql @@ -9,11 +9,6 @@ -- INSERT INTO director_activity_log (object_type, object_name, action_name, author, change_time, checksum) VALUES('object', 'foo', 'create', 'alex', CURRENT_TIMESTAMP, decode('cf23df2207d99a74fbe169e3eba035e633b65d94', 'hex')); -- --- --- Enumerable Types --- --- TODO: what about translation of the strings? - CREATE TYPE enum_activity_action AS ENUM('create', 'delete', 'modify'); CREATE TYPE enum_boolean AS ENUM('y', 'n'); CREATE TYPE enum_property_format AS ENUM('string', 'expression', 'json'); @@ -24,6 +19,9 @@ CREATE TYPE enum_command_object_type AS ENUM('object', 'template', 'external_obj CREATE TYPE enum_apply_object_type AS ENUM('object', 'template', 'apply'); CREATE TYPE enum_state_name AS ENUM('OK', 'Warning', 'Critical', 'Unknown', 'Up', 'Down'); CREATE TYPE enum_type_name AS ENUM('DowntimeStart', 'DowntimeEnd', 'DowntimeRemoved', 'Custom', 'Acknowledgement', 'Problem', 'Recovery', 'FlappingStart', 'FlappingEnd'); +CREATE TYPE enum_sync_rule_object_type AS ENUM('host', 'user'); +CREATE TYPE enum_sync_rule_update_policy AS ENUM('merge', 'override', 'ignore'); +CREATE TYPE enum_sync_property_merge_policy AS ENUM('override', 'merge'); CREATE TABLE director_dbversion ( @@ -73,7 +71,7 @@ COMMENT ON COLUMN director_generated_config.duration IS 'Config generation durat CREATE TABLE director_generated_file ( checksum bytea CHECK(LENGTH(checksum) = 20), - content text NOT NULL, + content text DEFAULT NULL, PRIMARY KEY (checksum) ); @@ -486,7 +484,7 @@ CREATE INDEX host_inheritance_host_parent ON icinga_host_inheritance (parent_hos CREATE TABLE icinga_host_field ( host_id integer NOT NULL, datafield_id integer NOT NULL, - is_required enum_boolean DEFAULT NULL, + is_required enum_boolean DEFAULT NOT NULL, PRIMARY KEY (host_id, datafield_id), CONSTRAINT icinga_host_field_host FOREIGN KEY (host_id) @@ -610,7 +608,7 @@ CREATE INDEX service_inheritance_service_parent ON icinga_service_inheritance (p CREATE TABLE icinga_service_field ( service_id integer NOT NULL, datafield_id integer NOT NULL, - is_required enum_boolean DEFAULT NULL, + is_required enum_boolean DEFAULT NOT NULL, PRIMARY KEY (service_id, datafield_id), CONSTRAINT icinga_service_field_service FOREIGN KEY (service_id) @@ -963,6 +961,184 @@ CREATE TABLE icinga_usergroup_parent ( CREATE INDEX usergroup_parent_usergroup ON icinga_usergroup_parent (usergroup_id); CREATE INDEX usergroup_parent_parent ON icinga_usergroup_parent (parent_usergroup_id); --- --- TODO: unfinished: see mysql.sql schema from sync_* --- + +CREATE TABLE import_source ( + id serial, + source_name character varying(64) NOT NULL, + key_column character varying(64) NOT NULL, + provider_class character varying(72) NOT NULL, + PRIMARY KEY (id) +); + +CREATE INDEX import_source_search_idx ON import_source (key_column); + + +CREATE TABLE import_source_setting ( + source_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text NOT NULL, + PRIMARY KEY (source_id, setting_name), + CONSTRAINT import_source_settings_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE CASCADE + ON UPDATE CASCADE +); + +CREATE INDEX import_source_setting_source ON import_source_setting (source_id); + + +CREATE TABLE imported_rowset ( + checksum bytea CHECK(LENGTH(checksum) = 20), + PRIMARY KEY (checksum) +); + + +CREATE TABLE import_run ( + id serial, + source_id integer NOT NULL, + rowset_checksum bytea CHECK(LENGTH(rowset_checksum) = 20), + start_time timestamp with time zone NOT NULL, + end_time timestamp with time zone NOT NULL, + succeeded enum_boolean DEFAULT NULL, + PRIMARY KEY (id), + CONSTRAINT import_run_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + CONSTRAINT import_run_rowset + FOREIGN KEY (rowset_checksum) + REFERENCES imported_rowset (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX import_run_import_source ON import_run (source_id); +CREATE INDEX import_run_rowset ON import_run (rowset_checksum); + + +CREATE TABLE imported_row ( + checksum bytea CHECK(LENGTH(checksum) = 20), + object_name character varying(255) NOT NULL, + PRIMARY KEY (checksum) +); + +COMMENT ON COLUMN imported_row.checksum IS 'sha1(object_name;property_checksum;...)'; + + +CREATE TABLE imported_rowset_row ( + rowset_checksum bytea CHECK(LENGTH(checksum) = 20), + row_checksum bytea CHECK(LENGTH(checksum) = 20), + PRIMARY KEY (rowset_checksum, row_checksum), + CONSTRAINT imported_rowset_row_rowset + FOREIGN KEY (rowset_checksum) + REFERENCES imported_rowset (checksum) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT imported_rowset_row_row + FOREIGN KEY (row_checksum) + REFERENCES imported_row (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX imported_rowset_row_rowset_checksum ON imported_rowset_row (rowset_checksum); +CREATE INDEX imported_rowset_row_row_checksum ON imported_rowset_row (row_checksum); + +CREATE TABLE imported_property ( + checksum bytea CHECK(LENGTH(checksum) = 20), + property_name character varying(64) NOT NULL, + property_value text NOT NULL, + format enum_property_format, + PRIMARY KEY (checksum) +); + +CREATE INDEX imported_property_search_idx ON imported_property (property_name); + +CREATE TABLE imported_row_property ( + row_checksum bytea CHECK(LENGTH(row_checksum) = 20), + property_checksum bytea CHECK(LENGTH(property_checksum) = 20), + PRIMARY KEY (row_checksum, property_checksum), + CONSTRAINT imported_row_property_row + FOREIGN KEY (row_checksum) + REFERENCES imported_row (checksum) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT imported_row_property_property + FOREIGN KEY (property_checksum) + REFERENCES imported_property (checksum) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX imported_row_property_row_checksum ON imported_row_property (row_checksum); +CREATE INDEX imported_row_property_property_checksum ON imported_row_property (property_checksum); + +CREATE TABLE sync_rule ( + id serial, + rule_name character varying(255) NOT NULL, + object_type enum_sync_rule_object_type NOT NULL, + update_policy enum_sync_rule_update_policy NOT NULL, + purge_existing enum_boolean NOT NULL DEFAULT 'n', + filter_expression text DEFAULT NULL, + PRIMARY KEY (id) +); + + +CREATE TABLE sync_property ( + id serial, + rule_id integer NOT NULL, + source_id integer NOT NULL, + source_expression character varying(255) NOT NULL, + destination_field character varying(64), + priority smallint NOT NULL, + filter_expression text DEFAULT NULL, + merge_policy enum_sync_property_merge_policy NOT NULL, + PRIMARY KEY (id), + CONSTRAINT sync_property_rule + FOREIGN KEY (rule_id) + REFERENCES sync_rule (id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT sync_property_source + FOREIGN KEY (source_id) + REFERENCES import_source (id) + ON DELETE RESTRICT + ON UPDATE CASCADE +); + +CREATE INDEX sync_property_rule ON sync_property (rule_id); +CREATE INDEX sync_property_source ON sync_property (source_id); + + +CREATE TABLE import_row_modifier ( + id serial, + property_id integer NOT NULL, + provider_class character varying(72) NOT NULL, + PRIMARY KEY (id) +); + + +CREATE TABLE import_row_modifier_setting ( + modifier_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text DEFAULT NULL, + PRIMARY KEY (modifier_id) +); + + +CREATE TABLE director_datafield_setting ( + datafield_id integer NOT NULL, + setting_name character varying(64) NOT NULL, + setting_value text NOT NULL, + PRIMARY KEY (datafield_id, setting_name), + CONSTRAINT datafield_id_settings + FOREIGN KEY (datafield_id) + REFERENCES director_datafield (id) + ON DELETE CASCADE + ON UPDATE CASCADE +); + +CREATE INDEX director_datafield_datafield ON director_datafield_setting (datafield_id); + From 91ebe4ce32bcaeefaa9e370fe8812e560bc7569b Mon Sep 17 00:00:00 2001 From: Alexander Fuhr Date: Thu, 30 Jul 2015 14:57:26 +0200 Subject: [PATCH 56/92] schema/pgsql-changes: rename upgrade_24-34.sql to upgrade_34.sql --- schema/pgsql-changes/{upgrade_24-34.sql => upgrade_34.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename schema/pgsql-changes/{upgrade_24-34.sql => upgrade_34.sql} (100%) diff --git a/schema/pgsql-changes/upgrade_24-34.sql b/schema/pgsql-changes/upgrade_34.sql similarity index 100% rename from schema/pgsql-changes/upgrade_24-34.sql rename to schema/pgsql-changes/upgrade_34.sql From 3c8f3a7adeb32f99bf28dd591fdc7bed9cce9c5c Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 15:08:55 +0200 Subject: [PATCH 57/92] config/schema: add controller and view script --- application/controllers/SchemaController.php | 62 +++++++++++++++++++ application/forms/ConfigForm.php | 4 +- application/views/scripts/schema/schema.phtml | 10 +++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 application/controllers/SchemaController.php create mode 100644 application/views/scripts/schema/schema.phtml diff --git a/application/controllers/SchemaController.php b/application/controllers/SchemaController.php new file mode 100644 index 00000000..e216cfce --- /dev/null +++ b/application/controllers/SchemaController.php @@ -0,0 +1,62 @@ +schemas = array( + 'mysql' => $this->translate('MySQL schema'), + 'pgsql' => $this->translate('PostgreSQL schema'), + ); + } + + protected function tabs() + { + $tabs = $this->getTabs(); + foreach ($this->schemas as $type => $title) { + $tabs->add($type, array( + 'url' => 'director/schema/' . $type, + 'label' => $title, + )); + } + return $tabs; + } + + public function mysqlAction() + { + $this->serveSchema('mysql'); + } + + public function pgsqlAction() + { + $this->serveSchema('pgsql'); + } + + protected function serveSchema($type) + { + $schema = file_get_contents( + sprintf( + '%s/schema/%s.sql', + $this->Module()->getBasedir(), + $type + ) + ); + + if ($this->params->get('format') === 'sql') { + header('Content-type: application/octet-stream'); + header('Content-Disposition: attachment; filename=' . $type . '.sql'); + echo $schema; + exit; + // TODO: Shutdown + } else { + $this->tabs()->activate($type); + $this->view->title = $this->schemas[$type]; + $this->view->schema = $schema; + $this->render('schema'); + } + } +} diff --git a/application/forms/ConfigForm.php b/application/forms/ConfigForm.php index a5941548..4c9be27c 100644 --- a/application/forms/ConfigForm.php +++ b/application/forms/ConfigForm.php @@ -88,7 +88,9 @@ class ConfigForm extends QuickForm ); $link = $this->getView()->qlink( $this->translate('database schema'), - 'director/schema/' . $resource->getDbType() + 'director/schema/' . $resource->getDbType(), + null, + array('data-base-target' => '_next') ); $this->addHtmlHint(sprintf($hint, $link)); $this->moveSubmitToBottom(); diff --git a/application/views/scripts/schema/schema.phtml b/application/views/scripts/schema/schema.phtml new file mode 100644 index 00000000..1f900f5e --- /dev/null +++ b/application/views/scripts/schema/schema.phtml @@ -0,0 +1,10 @@ +
+ +

escape($title) ?>

+icon('download') ?>Download +
+ +
+
escape($schema) ?>
+
+ From 1fc7f6e2cba756adb03db22a2808f12b7777fcc3 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 15:39:09 +0200 Subject: [PATCH 58/92] QuickForm: dedicated method for special options --- library/Director/Web/Form/QuickForm.php | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index c13ff315..af267189 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -66,18 +66,28 @@ abstract class QuickForm extends Zend_Form public function __construct($options = null) { - if ($options !== null && array_key_exists('icingaModule', $options)) { - $this->icingaModule = $options['icingaModule']; - $this->icingaModuleName = $this->icingaModule->getName(); - unset($options['icingaModule']); - } - parent::__construct($options); + parent::__construct($this->handleOptions($options)); $this->setMethod('post'); $this->setAction(Url::fromRequest()); $this->createIdElement(); $this->regenerateCsrfToken(); } + protected function handleOptions($options = null) + { + if ($options === null) { + return $options; + } + + if (array_key_exists('icingaModule', $options)) { + $this->icingaModule = $options['icingaModule']; + $this->icingaModuleName = $this->icingaModule->getName(); + unset($options['icingaModule']); + } + + return $options; + } + protected function addSubmitButtonIfSet() { if (false !== ($label = $this->getSubmitLabel())) { From f5ebb06d8a1b42578d2e1ecd12cedbd5c58cf6c2 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 15:39:51 +0200 Subject: [PATCH 59/92] QuickForm: be strict on setting request only once --- library/Director/Web/Form/QuickForm.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index af267189..0deb86d6 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Director\Web\Form; use Icinga\Application\Icinga; use Icinga\Application\Modules\Module; +use Icinga\Exception\ProgrammingError; use Icinga\Web\Notification; use Icinga\Web\Request; use Icinga\Web\Url; @@ -155,6 +156,7 @@ abstract class QuickForm extends Zend_Form $element = $this->getElement(self::CSRF); } $element->setValue(CsrfToken::generate())->setIgnore(true); + return $this; } @@ -262,7 +264,7 @@ abstract class QuickForm extends Zend_Form public function handleRequest(Request $request = null) { if ($request !== null) { - $this->request = $request; + $this->setRequest($request); } $this->prepareElements(); @@ -354,6 +356,10 @@ abstract class QuickForm extends Zend_Form public function setRequest(Request $request) { + if ($this->request !== null) { + throw new ProgrammingError('Unable to set request twice'); + } + $this->request = $request; $this->onRequest(); return $this; From 9c03ef5b626c66dd3ac72fa3c074348a3976e310 Mon Sep 17 00:00:00 2001 From: Alexander Fuhr Date: Thu, 30 Jul 2015 15:47:38 +0200 Subject: [PATCH 60/92] schema/pgsql: fix the upgrade and the schema not null attribute fixes #9783 --- schema/pgsql-changes/upgrade_34.sql | 4 ++-- schema/pgsql.sql | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/schema/pgsql-changes/upgrade_34.sql b/schema/pgsql-changes/upgrade_34.sql index 6aed5e72..c8e57abe 100644 --- a/schema/pgsql-changes/upgrade_34.sql +++ b/schema/pgsql-changes/upgrade_34.sql @@ -1,6 +1,6 @@ ALTER TABLE director_generated_file ALTER COLUMN content SET DEFAULT NULL; -ALTER TABLE icinga_host_field ALTER COLUMN is_required SET DEFAULT NOT NULL; -ALTER TABLE icinga_service_field ALTER COLUMN is_required SET DEFAULT NOT NULL; +ALTER TABLE icinga_host_field ALTER COLUMN is_required SET NOT NULL; +ALTER TABLE icinga_service_field ALTER COLUMN is_required SET NOT NULL; CREATE TABLE import_source ( id serial, diff --git a/schema/pgsql.sql b/schema/pgsql.sql index aa09ddb0..b60f5787 100644 --- a/schema/pgsql.sql +++ b/schema/pgsql.sql @@ -484,7 +484,7 @@ CREATE INDEX host_inheritance_host_parent ON icinga_host_inheritance (parent_hos CREATE TABLE icinga_host_field ( host_id integer NOT NULL, datafield_id integer NOT NULL, - is_required enum_boolean DEFAULT NOT NULL, + is_required enum_boolean NOT NULL, PRIMARY KEY (host_id, datafield_id), CONSTRAINT icinga_host_field_host FOREIGN KEY (host_id) @@ -608,7 +608,7 @@ CREATE INDEX service_inheritance_service_parent ON icinga_service_inheritance (p CREATE TABLE icinga_service_field ( service_id integer NOT NULL, datafield_id integer NOT NULL, - is_required enum_boolean DEFAULT NOT NULL, + is_required enum_boolean NOT NULL, PRIMARY KEY (service_id, datafield_id), CONSTRAINT icinga_service_field_service FOREIGN KEY (service_id) @@ -1141,4 +1141,3 @@ CREATE TABLE director_datafield_setting ( ); CREATE INDEX director_datafield_datafield ON director_datafield_setting (datafield_id); - From 3b71f2219fe7cea88e512789ab53f5a87aa4e9c6 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 16:24:17 +0200 Subject: [PATCH 61/92] ServiceTemplates: add controller and table --- .../controllers/ServicetemplatesController.php | 7 +++++++ application/tables/IcingaServiceTable.php | 7 ++++++- application/tables/IcingaServiceTemplateTable.php | 13 +++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 application/controllers/ServicetemplatesController.php create mode 100644 application/tables/IcingaServiceTemplateTable.php diff --git a/application/controllers/ServicetemplatesController.php b/application/controllers/ServicetemplatesController.php new file mode 100644 index 00000000..0434ecaa --- /dev/null +++ b/application/controllers/ServicetemplatesController.php @@ -0,0 +1,7 @@ +connection()->getConnection(); $query = $db->select()->from( @@ -47,4 +47,9 @@ class IcingaServiceTable extends QuickTable return $query; } + + public function getBaseQuery() + { + return $this->getUnfilteredQuery()->where('s.object_type = ?', 'object'); + } } diff --git a/application/tables/IcingaServiceTemplateTable.php b/application/tables/IcingaServiceTemplateTable.php new file mode 100644 index 00000000..e5cbe359 --- /dev/null +++ b/application/tables/IcingaServiceTemplateTable.php @@ -0,0 +1,13 @@ +getUnfilteredQuery()->where('s.object_type = ?', 'template'); + } +} From 77dc7e24d3009e782120d387c70ab50243689e7f Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 16:50:48 +0200 Subject: [PATCH 62/92] IcingaServiceForm: distinct objects/templates --- application/forms/IcingaServiceForm.php | 36 +++++++------------------ 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/application/forms/IcingaServiceForm.php b/application/forms/IcingaServiceForm.php index dd4cb533..954d4944 100644 --- a/application/forms/IcingaServiceForm.php +++ b/application/forms/IcingaServiceForm.php @@ -8,39 +8,21 @@ class IcingaServiceForm extends DirectorObjectForm { public function setup() { - $isTemplate = isset($_POST['object_type']) && $_POST['object_type'] === 'template'; - $this->addElement('select', 'object_type', array( - 'label' => $this->translate('Object type'), - 'description' => $this->translate('Whether this should be a template'), - 'multiOptions' => array( - null => '- please choose -', - 'object' => 'Service object', - 'template' => 'Service template', - ), - 'class' => 'autosubmit' + $this->addElement('text', 'object_name', array( + 'label' => $this->translate('Name'), + 'required' => true, + 'description' => $this->translate('Name for the Icinga object you are going to create') )); - if ($isTemplate) { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Service template name'), - 'required' => true, - 'description' => $this->translate('Name for the Icinga service template you are going to create') - )); - } else { - $this->addElement('text', 'object_name', array( - 'label' => $this->translate('Servicename'), - 'required' => true, - 'description' => $this->translate('Servicename for the Icinga service you are going to create') - )); - } - $this->addElement('text', 'groups', array( 'label' => $this->translate('Servicegroups'), 'description' => $this->translate('One or more comma separated servicegroup names') )); + $this->addImportsElement(); - $this->addCheckCommandElement() - ->addCheckFlagElements() - ->addImportsElement(); + if ($this->isTemplate()) { + $this->addCheckCommandElement() + ->addCheckFlagElements(); + } } } From bdb7d22e99b1dc550982dccf6cc824640c0ec5a6 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Thu, 30 Jul 2015 16:51:20 +0200 Subject: [PATCH 63/92] ObjectController: fix inverted titles --- library/Director/Web/Controller/ObjectController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Director/Web/Controller/ObjectController.php b/library/Director/Web/Controller/ObjectController.php index 032ea127..a7a72dd5 100644 --- a/library/Director/Web/Controller/ObjectController.php +++ b/library/Director/Web/Controller/ObjectController.php @@ -113,9 +113,9 @@ abstract class ObjectController extends ActionController if ($this->params->get('type') === 'template') { $form->setObjectType('template'); - $title = $this->translate('Add new Icinga %s'); - } else { $title = $this->translate('Add new Icinga %s template'); + } else { + $title = $this->translate('Add new Icinga %s'); } $this->view->title = sprintf($title, ucfirst($ltype)); From 48a8e1ab63bd39eb2273c26d20fbe72c68a30250 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:33:09 +0200 Subject: [PATCH 64/92] IcingaObjectImports: simplify code --- library/Director/Objects/IcingaObjectImports.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/library/Director/Objects/IcingaObjectImports.php b/library/Director/Objects/IcingaObjectImports.php index b8ab2c72..470c1244 100644 --- a/library/Director/Objects/IcingaObjectImports.php +++ b/library/Director/Objects/IcingaObjectImports.php @@ -158,19 +158,9 @@ class IcingaObjectImports implements Iterator, Countable, IcingaConfigRenderer if ($import instanceof $class) { $this->imports[$import->object_name] = $import; } elseif (is_string($import)) { - $query = $this->object->getDb()->select()->from( - $this->object->getTableName() - )->where('object_name = ?', $import); - $imports = $class::loadAll($connection, $query, 'object_name'); + $import = $class::load($import, $connection); + $this->imports[$import->object_name] = $import; } - if (! array_key_exists($import, $imports)) { - throw new ProgrammingError( - 'The import "%s" doesn\'t exists.', - $import - ); - } - - $this->imports[$import] = $imports[$import]; $this->modified = true; $this->refreshIndex(); From 4780e112413a73057d3587ffcba4034996fc4fba Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:34:14 +0200 Subject: [PATCH 65/92] CustomVariable: add delete() method --- library/Director/CustomVariable/CustomVariable.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/Director/CustomVariable/CustomVariable.php b/library/Director/CustomVariable/CustomVariable.php index 9f620a1b..4a824cf4 100644 --- a/library/Director/CustomVariable/CustomVariable.php +++ b/library/Director/CustomVariable/CustomVariable.php @@ -45,12 +45,17 @@ abstract class CustomVariable implements IcingaConfigRenderer } // TODO: implement delete() - public function hasBeenDeleted() { return $this->deleted; } + public function delete() + { + $this->deleted = true; + return $this; + } + // TODO: abstract public function getDbValue() { From 3a96f9ebe4344ea9c26b2c22cf93e3fb7c20bd0f Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:35:49 +0200 Subject: [PATCH 66/92] CustomVariables: handle deleted vars --- library/Director/CustomVariable/CustomVariables.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/Director/CustomVariable/CustomVariables.php b/library/Director/CustomVariable/CustomVariables.php index 5c830c1e..31acf9ac 100644 --- a/library/Director/CustomVariable/CustomVariables.php +++ b/library/Director/CustomVariable/CustomVariables.php @@ -89,7 +89,12 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer protected function refreshIndex() { - $this->idx = array_keys($this->vars); + $this->idx = array(); + foreach ($this->vars as $name => $var) { + if (! $var->hasBeenDeleted()) { + $this->idx[] = $name; + } + } } public static function loadForStoredObject(IcingaObject $object) @@ -223,10 +228,11 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer public function __unset($key) { if (! array_key_exists($key, $this->vars)) { - throw new Exception('Trying to unset invalid key'); + return; } - unset($this->vars[$key]); + $this->vars[$key]->delete(); + $this->modified = true; $this->refreshIndex(); } From 362eddb75cd9916ce7a9447f401b055a47f6afb3 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:38:22 +0200 Subject: [PATCH 67/92] Util: Manager is now Auth in Web 2 --- library/Director/Util.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Director/Util.php b/library/Director/Util.php index 8d74516e..09e9840d 100644 --- a/library/Director/Util.php +++ b/library/Director/Util.php @@ -2,7 +2,7 @@ namespace Icinga\Module\Director; -use Icinga\Authentication\Manager; +use Icinga\Authentication\Auth; use Icinga\Data\ResourceFactory; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Web\Url; @@ -32,7 +32,7 @@ class Util public static function auth() { if (self::$auth === null) { - self::$auth = Manager::getInstance(); + self::$auth = Auth::getInstance(); } return self::$auth; } From f4e992f6da1a7d47174b82ec3f84f83e2950f285 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:40:55 +0200 Subject: [PATCH 68/92] CustomVariables: allow access to unmodified vars --- library/Director/CustomVariable/CustomVariables.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/Director/CustomVariable/CustomVariables.php b/library/Director/CustomVariable/CustomVariables.php index 31acf9ac..5e3991c0 100644 --- a/library/Director/CustomVariable/CustomVariables.php +++ b/library/Director/CustomVariable/CustomVariables.php @@ -178,6 +178,11 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer return $this; } + public function getOriginalVars() + { + return $this->storedVars; + } + public function toConfigString() { $out = ''; From 43fc6fc42ba49a19c81c102c3324e5969f6b2ef5 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:46:20 +0200 Subject: [PATCH 69/92] CustomVariables: clone vars, may not suffice --- library/Director/CustomVariable/CustomVariables.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/Director/CustomVariable/CustomVariables.php b/library/Director/CustomVariable/CustomVariables.php index 5e3991c0..61aa6cc8 100644 --- a/library/Director/CustomVariable/CustomVariables.php +++ b/library/Director/CustomVariable/CustomVariables.php @@ -174,7 +174,10 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer public function setUnmodified() { $this->modified = false; - $this->storedVars = $this->vars; + $this->storedVars = array(); + foreach ($this->vars as $key => $var) { + $this->storedVars[$key] = clone($var); + } return $this; } From 24f7e36e927b7d295a7941024ca366711897038e Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:47:03 +0200 Subject: [PATCH 70/92] DataTypeSqlQuery: do not break form on errors --- library/Director/DataType/DataTypeSqlQuery.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/library/Director/DataType/DataTypeSqlQuery.php b/library/Director/DataType/DataTypeSqlQuery.php index 06a61693..fa1b05a2 100644 --- a/library/Director/DataType/DataTypeSqlQuery.php +++ b/library/Director/DataType/DataTypeSqlQuery.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Director\DataType; +use Exception; use Icinga\Data\Db\DbConnection; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Module\Director\Web\Hook\DataTypeHook; @@ -17,11 +18,22 @@ class DataTypeSqlQuery extends DataTypeHook public function getFormElement($name, QuickForm $form) { + try { + $data = $this->fetchData(); + $error = false; + } catch (Exception $e) { + $data = array(); + $error = sprintf($form->translate('Unable to fetch data: %s'), $e->getMessage()); + } + $element = $form->createElement('select', $name, array( - 'multiOptions' => array(null => '- please choose -') + - $this->fetchData(), + 'multiOptions' => $form->optionalEnum($data), )); + if ($error) { + $element->addError($error); + } + return $element; } From 51672e33bdef44664287b24f2c211e75198e82cd Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:48:17 +0200 Subject: [PATCH 71/92] QuickForm: addHtml VS addHtmlNote (note is styled) --- library/Director/Web/Form/QuickForm.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index 0deb86d6..b2792da8 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -177,11 +177,16 @@ abstract class QuickForm extends Zend_Form } public function addHtmlHint($html, $options = array()) + { + return $this->addHtml('
' . $html . '
', $options); + } + + public function addHtml($html, $options = array()) { $name = '_HINT' . ++$this->hintCount; $this->addElement('note', $name, $options); $this->getElement($name) - ->setValue('
' . $html . '
') + ->setValue($html) ->setIgnore(true) ->removeDecorator('Label'); From 299251276e78218fd5a9c361d76d2dccc0f01b3a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:50:05 +0200 Subject: [PATCH 72/92] ObjectController: improve title settings, clean up --- .../Director/Web/Controller/ObjectController.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/Director/Web/Controller/ObjectController.php b/library/Director/Web/Controller/ObjectController.php index a7a72dd5..0d7b077e 100644 --- a/library/Director/Web/Controller/ObjectController.php +++ b/library/Director/Web/Controller/ObjectController.php @@ -85,17 +85,21 @@ abstract class ObjectController extends ActionController 'icinga' . ucfirst($type) )->setDb($this->db()); $form->loadObject($this->params->get('name')); + $object = $form->getObject(); $url = Url::fromPath( sprintf('director/%s', $ltype), - array('name' => $form->getObject()->object_name) + array('name' => $object->object_name) ); $form->setSuccessUrl($url); - $this->view->title = sprintf( - $this->translate('Modify Icinga %s'), - ucfirst($ltype) - ); + if ($object->isTemplate()) { + $title = $this->translate('Modify Icinga %s template'); + } else { + $title = $this->translate('Modify Icinga %s'); + } + + $this->view->title = sprintf($title, ucfirst($ltype)); $this->view->form->handleRequest(); $this->render('object/form', null, true); } From f5bf209a8ab79032c9250472489893583b80ec26 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:50:36 +0200 Subject: [PATCH 73/92] DirectorActivityLog: going towards logging deep --- .../scripts/show/activitylog-modify.phtml | 9 +++- .../Director/Objects/DirectorActivityLog.php | 46 +++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/application/views/scripts/show/activitylog-modify.phtml b/application/views/scripts/show/activitylog-modify.phtml index f9388df4..b392988c 100644 --- a/application/views/scripts/show/activitylog-modify.phtml +++ b/application/views/scripts/show/activitylog-modify.phtml @@ -17,12 +17,19 @@ foreach ($old as $key => $value) { $modified = array_key_exists($key, $new); if ($value === null && ! $modified) continue; + + if (is_array($value)) $value = implode(', ', $value); + if (is_object($value)) $value = json_encode($value); + echo ' ' . $this->escape($key) . ''; if ($modified) { + $newval = $new->$key; + if (is_array($newval)) $newval = implode(', ', $newval); + if (is_object($newval)) $newval = json_encode($newval); printf( '%s %s', $this->escape($value), - $this->escape($new->$key) + $this->escape($newval) ); } else { echo $this->escape($value); diff --git a/library/Director/Objects/DirectorActivityLog.php b/library/Director/Objects/DirectorActivityLog.php index 3da05baf..8f4e4f38 100644 --- a/library/Director/Objects/DirectorActivityLog.php +++ b/library/Director/Objects/DirectorActivityLog.php @@ -5,7 +5,7 @@ namespace Icinga\Module\Director\Objects; use Icinga\Module\Director\Data\Db\DbObject; use Icinga\Module\Director\Db; use Icinga\Module\Director\Util; -use Icinga\Authentication\Manager as Auth; +use Icinga\Authentication\Auth; class DirectorActivityLog extends DbObject { @@ -48,6 +48,46 @@ class DirectorActivityLog extends DbObject if ($object->supportsGroups()) { $props['groups'] = $object->groups()->listGroupNames(); } + if ($object->supportsCustomVars()) { + $props['vars'] = $object->getVars(); + } + + return json_encode($props); + } + + protected static function prepareModifiedProperties(DbObject $object) + { + $props = $object->getModifiedProperties(); + if ($object->supportsCustomVars()) { + $mod = array(); + foreach ($object->vars() as $name => $var) { + if ($var->hasBeenModified()) { + $mod[$name] = $var->getValue(); + } + } + if (! empty($mod)) { + $props['vars'] = (object) $mod; + } + } + if ($object->supportsGroups()) { + // $props['groups'] = $object->groups()->listGroupNames(); + } + + return json_encode($props); + } + + protected static function prepareOriginalProperties(DbObject $object) + { + $props = $object->getModifiedProperties(); + if ($object->supportsCustomVars()) { + $props['vars'] = (object) array(); + foreach ($object->vars()->getOriginalVars() as $name => $var) { + $props['vars']->$name = $var->getValue(); + } + } + if ($object->supportsGroups()) { + // $props['groups'] = $object->groups()->listGroupNames(); + } return json_encode($props); } @@ -76,8 +116,8 @@ class DirectorActivityLog extends DbObject 'action_name' => 'modify', 'author' => self::username(), 'object_type' => $object->getTableName(), - 'old_properties' => json_encode($object->getOriginalProperties()), - 'new_properties' => json_encode($object->getModifiedProperties()), + 'old_properties' => self::prepareOriginalProperties($object), + 'new_properties' => self::prepareModifiedProperties($object), 'change_time' => date('Y-m-d H:i:s'), // TODO -> postgres! 'parent_checksum' => $db->getLastActivityChecksum() ); From 591d93392911c1e2711cd3704e35d4dad28d3384 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:51:41 +0200 Subject: [PATCH 74/92] DirectorObjectForm: reorganize, simplify, improve --- .../Director/Web/Form/DirectorObjectForm.php | 384 +++++++++++------- 1 file changed, 229 insertions(+), 155 deletions(-) diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index ef402e40..dfbdb134 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -41,31 +41,6 @@ abstract class DirectorObjectForm extends QuickForm return; } - if ($object->supportsCustomVars()) { - $this->addElement('note', '_newvar_hint', array('label' => 'New custom variable')); - $this->addElement('text', '_newvar_name', array( - 'label' => 'Name' - )); - $this->addElement('text', '_newvar_value', array( - 'label' => 'Value' - )); - $this->addElement('select', '_newvar_format', array( - 'label' => 'Type', - 'multiOptions' => array('string' => $this->translate('String')) - )); - } - - if (false && $object->supportsRanges()) { - /* TODO implement when new logic is there - $this->addElement('note', '_newrange_hint', array('label' => 'New range')); - $this->addElement('text', '_newrange_name', array( - 'label' => 'Name' - )); - $this->addElement('text', '_newrange_value', array( - 'label' => 'Value' - )); - */ - } } protected function isTemplate() @@ -73,23 +48,117 @@ abstract class DirectorObjectForm extends QuickForm return $this->objectType === 'template'; } - protected function handleIcingaObject(& $values) + protected function handleImports($object, & $values) { - $object = $this->object(); - $handled = array(); - - if ($object->supportsGroups()) { - if (array_key_exists('groups', $values)) { - $object->groups()->set( - preg_split('/\s*,\s*/', $values['groups'], -1, PREG_SPLIT_NO_EMPTY) - ); - $handled['groups'] = true; - } + if (! $object->supportsImports()) { + return; } - if ($object->supportsCustomVars()) { + if (array_key_exists('imports', $values)) { + $value = $values['imports']; + unset($values['imports']); + $object->clearImportedObjects(); + $object->imports()->set($value); + } + $el = $this->getElement('imports'); + if ($el) { + $el->setMultiOptions($this->enumAllowedTemplates()); + $el->setValue($object->imports()->listImportNames()); + } + } + + protected function handleRanges($object, & $values) + { + if (! $object->supportsRanges()) { + return; + } + + $key = 'ranges'; + $object = $this->object(); + + /* Sample: + + array( + 'monday' => 'eins', + 'tuesday' => '00:00-24:00', + 'sunday' => 'zwei', + ); + + */ + if (array_key_exists($key, $values)) { + $object->ranges()->set($values[$key]); + unset($values[$key]); + } + + foreach ($object->ranges()->getRanges() as $key => $value) { + $this->addRange($key, $value); + } + + /* + // TODO implement when new logic is there + $this->addElement('note', '_newrange_hint', array('label' => 'New range')); + $this->addElement('text', '_newrange_name', array( + 'label' => 'Name' + )); + $this->addElement('text', '_newrange_value', array( + 'label' => 'Value' + )); + */ + } + + protected function handleGroups($object, & $values) + { + if (! $object->supportsGroups()) { + return; + } + + if (array_key_exists('groups', $values)) { + $value = $values['groups']; + unset($values['groups']); + + // TODO: Drop this once we have arrays everwhere + if (is_string($value)) { + $value = preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); + } + + $object->groups()->set($value); + } + } + + protected function handleProperties($object, & $values) + { + if ($this->hasBeenSent()) { + $object->setProperties($values); + } + + $props = $object->getProperties(); + if (! $object instanceof IcingaObject) { + $this->setDefaults($props); + return $this; + } + + $inherited = $object->getInheritedProperties(); + $origins = $object->getOriginsProperties(); + + foreach ($props as $k => $v) { + if (property_exists($inherited, $k)) { + $this->setElementValue($k, $v, $inherited->$k, $origins->$k); + } else { + $this->setElementValue($k, $v); + } + } + } + + protected function handleCustomVars($object, & $values) + { + if (! $object->supportsCustomVars()) { + return; + } + + if ($this->hasBeenSent()) { $vars = array(); + $handled = array(); $newvar = array( 'type' => 'string', 'name' => null, @@ -109,39 +178,83 @@ abstract class DirectorObjectForm extends QuickForm } foreach ($vars as $k => $v) { - $this->object->vars()->$k = $v; + if ($v === '' || $v === null) { + unset($object->vars()->$k); + } else { + $object->vars()->$k = $v; + } } if ($newvar['name'] && $newvar['value']) { - $this->object->vars()->{$newvar['name']} = $newvar['value']; + $object->vars()->{$newvar['name']} = $newvar['value']; + } + + foreach ($handled as $key) { + unset($values[$key]); } } - if ($object->supportsImports()) { - if (array_key_exists('imports', $values)) { - $value = $values['imports']; + $vars = $object->getVars(); - // TODO: Compat for comma separated string, check if still needed - if (! is_array($value)) { - $value = preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); + $fields = $object->getResolvedFields(); + $inherits = $object->getInheritedVars(); + $origins = $object->getOriginsVars(); + + foreach ($fields as $field) { + $varname = $field->varname; + + // Get value from the related varname if set: + if (property_exists($vars, $varname)) { + $value = $vars->$varname; + } else { + $value = null; + } + + if (property_exists($inherits, $varname)) { + $inheritedValue = $inherits->$varname; + $inheritFrom = $origins->$varname; + if ($inheritFrom === $object->object_name) { + $inherited = false; + } else { + $inherited = true; } - - $object->imports()->set($value); - $handled['imports'] = true; - $object->clearImportedObjects(); + } else { + $inheritedValue = null; + $inheritFrom = false; + $inherited = false; } + + $this->addField($field, $value, $inheritedValue, $inheritFrom); } - if ($object->supportsRanges()) { - $object->ranges()->set(array( - 'monday' => 'eins', - 'tuesday' => '00:00-24:00', - 'sunday' => 'zwei', + // Additional vars + foreach ($vars as $key => $value) { + // Did we already create a field for this var? Then skip it: + if (array_key_exists($key, $fields)) { + continue; + } + + // Show inheritance information in case we inherited this var: + if (isset($inherited->$key)) { + $this->addCustomVar($key, $value, $inherited->$key, $origins->$key); + } else { + $this->addCustomVar($key, $value); + } + + } + + if ($object->isTemplate()) { + $this->addHtml('

Add a custom variable

'); + $this->addElement('text', '_newvar_name', array( + 'label' => 'Name' + )); + $this->addElement('text', '_newvar_value', array( + 'label' => 'Value' + )); + $this->addElement('select', '_newvar_format', array( + 'label' => 'Type', + 'multiOptions' => array('string' => $this->translate('String')) )); - } - - foreach ($handled as $key => $value) { - unset($values[$key]); } } @@ -151,25 +264,7 @@ abstract class DirectorObjectForm extends QuickForm return $this; } - public function addFields() - { - $object = $this->object(); - $fields = $object->getResolvedFields(); - $vars = $object->vars(); - - foreach ($fields as $field) { - $varname = $field->varname; - if (isset($vars->$varname)) { - $value = $vars->{$varname}->getValue(); - } else { - $value = null; - } -$inherited = null; // Just testing - $this->addField($field, $value, $inherited); - } - } - - protected function addField($field, $value = null, $inherited = null) + protected function addField($field, $value = null, $inherited = null, $inheritedFrom = null) { $datafield = DirectorDatafield::load($field->datafield_id, $this->getDb()); $datatype = new $datafield->datatype; @@ -181,15 +276,17 @@ $inherited = null; // Just testing $el->setLabel($datafield->caption); $el->setDescription($datafield->description); - if ($field->is_required === 'y') { + if ($field->is_required === 'y' && ! $this->isTemplate()) { $el->setRequired(true); } $this->addElement($el); - $this->setElementValue($name, $value, $inherited); + $this->setElementValue($name, $value, $inherited, $inheritedFrom); + + return $el; } - protected function setElementValue($name, $value = null, $inherited = null) + protected function setElementValue($name, $value = null, $inherited = null, $inheritedFrom = null) { $el = $this->getElement($name); if (! $el) { @@ -200,44 +297,38 @@ $inherited = null; // Just testing $el->setValue($value); } - if ($inherited === null) { + if ($inherited === null || empty($inherited)) { return; } - $strInherited = $this->translate('(inherited)'); if ($el instanceof Zf_Select) { $multi = $el->getMultiOptions(); if (array_key_exists($inherited, $multi)) { - $multi[null] = $multi[$inherited] . ' ' . $strInherited; + $multi[null] = $multi[$inherited] . sprintf(' (%s)', $inheritedFrom); } else { - $multi[null] = $strInherited; + $multi[null] = $this->translate('- inherited -'); } $el->setMultiOptions($multi); } else { - $el->setAttrib('placeholder', $inherited . ' ' . $strInherited); + $el->setAttrib('placeholder', $inherited . sprintf(' (%s)', $inheritedFrom)); } } public function onSuccess() { - $object = $this->object; - $values = $this->getValues(); - if ($object instanceof IcingaObject) { - $this->handleIcingaObject($values); - if (! array_key_exists('object_type', $values)) { - $object->object_type = $this->objectType; - } + $object = $this->object(); + if ($object->hasBeenModified()) { + + $msg = sprintf( + $object->hasBeenLoadedFromDb() + ? $this->translate('The Icinga %s has successfully been stored') + : $this->translate('A new Icinga %s has successfully been created'), + $this->translate($this->getObjectName()) + ); + $object->store($this->db); + } else { + $msg = $this->translate('No action taken, object has not been modified'); } - $object->setProperties($values); - - $msg = sprintf( - $object->hasBeenLoadedFromDb() - ? 'The Icinga %s has successfully been stored' - : 'A new Icinga %s has successfully been created', - $this->translate($this->getObjectName()) - ); - - $object->store($this->db); $this->redirectOnSuccess($msg); } @@ -288,71 +379,54 @@ $inherited = null; // Just testing return $this->objectName; } + protected function onRequest() + { + $object = $this->object(); + $values = array(); + if ($this->hasBeenSent()) { + $post = $this->getRequest()->getPost(); + foreach ($post as $key => $value) { + $el = $this->getElement($key); + if ($el && ! $el->getIgnore()) { + $values[$key] = $value; + } + } + } + + if ($object instanceof IcingaObject) { + if (! $object->hasBeenLoadedFromDb()) { + $object->object_type = $this->objectType; + } + $this->handleImports($object, $values); + $this->handleCustomVars($object, $values); + $this->handleGroups($object, $values); + $this->handleRanges($object, $values); + } + + $this->handleProperties($object, $values); + + $this->moveSubmitToBottom(); + } + public function loadObject($id) { $class = $this->getObjectClassname(); - $object = $this->object = $class::load($id, $this->db); - if ($object instanceof IcingaObject) { - $this->objectType = $object->object_type; - } + $this->object = $class::load($id, $this->db); + // TODO: hmmmm... if (! is_array($id)) { $this->addHidden('id'); } - $this->prepareElements(); - - $props = $object->getProperties(); - if (! $object instanceof IcingaObject) { - $this->setDefaults($props); - return $this; - } - - $inherited = $this->object->getInheritedProperties(); - - foreach ($props as $k => $v) { - $i = property_exists($inherited, $k) ? $inherited->$k : null; - $this->setElementValue($k, $v, $i); - } - - if ($object->supportsGroups()) { - $this->getElement('groups')->setValue( - implode(', ', $object->groups()->listGroupNames()) - ); - } - - if ($object->supportsImports()) { - $el = $this->getElement('imports'); - if ($el) { - $el->setMultiOptions($this->enumAllowedTemplates()); - $el->setValue($object->imports()->listImportNames()); - } - } - - if ($object->supportsFields() && ! $object->isTemplate()) { - foreach ($this->object->vars() as $key => $value) { - $this->addCustomVar($key, $value); - } - } - - if ($object->supportsRanges()) { - /* TODO implement when new logic for customvars is there - foreach ($this->object->ranges()->getRanges() as $key => $value) { - $this->addRange($key, $value); - } - */ - } - - $this->moveSubmitToBottom(); return $this; } - protected function addCustomVar($key, $range) + protected function addCustomVar($key, $value, $inherited = null, $inheritedFrom = null) { - $this->addElement('text', 'var_' . $key, array( - 'label' => 'vars.' . $key, - 'value' => $range->getValue() - )); + $label = 'vars.' . $key; + $key = 'var_' . $key; + $this->addElement('text', $key, array('label' => $label)); + $this->setElementValue($key, $value, $inherited, $inheritedFrom); } protected function addRange($key, $range) From 40599fe8248ba02e8d4a06c6bc908baf36367c47 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:52:19 +0200 Subject: [PATCH 75/92] css/module.less: form style --- public/css/module.less | 50 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/public/css/module.less b/public/css/module.less index dfbcf526..2837a5b1 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -1,3 +1,45 @@ +input, select, select option, textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +select::-ms-expand, input::-ms-expand, textarea::-ms-expand { /* for IE 11 */ + display: none; +} + +select { + border: 1px solid transparent; + cursor: pointer; +} + +input, textarea { + border: 1px solid transparent; + padding-left: 0.5em; +} + +select:hover, input:hover, textarea:hover, select:focus, input:focus, textarea:focus { + border: 1px solid #ddd; +} + +select[value=""] { + color: blue; +} + +select option { + color: inherit; + padding-left: 0.5em; +} + +select option[value=""] { + color: #aaa; +} + +/* TEMP */ +p.description { +display: none; +} + ul.main-actions { margin: 0; @@ -39,6 +81,11 @@ ul.main-actions { /* BEGIN Forms */ form dt label { width: auto; + font-weight: normal; + + &.required { + font-weight: bold; + } } form dd { @@ -48,7 +95,8 @@ form dd { form dt { display: inline-block; - min-width: 16em; + min-width: 12em; + width: 30%; } form dd:after { From c8e9369ddef8580a36442e464e94c71c8ee57a6b Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 14:52:46 +0200 Subject: [PATCH 76/92] IcingaObject: improve/reorganize resolver code --- library/Director/Objects/IcingaObject.php | 72 +++++++++++++++-------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index 99eed143..89d53cf6 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -155,6 +155,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->getInherited('Properties'); } + public function getOriginsProperties() + { + return $this->getOrigins('Properties'); + } + public function resolveProperties() { return $this->resolve('Properties'); @@ -170,6 +175,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->getInherited('Fields'); } + public function getOriginsFields() + { + return $this->getOrigins('Fields'); + } + public function resolveFields() { return $this->resolve('Fields'); @@ -190,6 +200,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $this->resolve('Vars'); } + public function getOriginsVars() + { + return $this->getOrigins('Vars'); + } + public function getVars() { $vars = (object) array(); @@ -214,43 +229,52 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer return $res['_INHERITED_']; } + protected function getOrigins($what) + { + $func = 'resolve' . $what; + $res = $this->$func(); + return $res['_ORIGINS_']; + } + protected function resolve($what) { $vals = array(); - $vals['_MERGED_'] = (object) array(); + $vals['_MERGED_'] = (object) array(); $vals['_INHERITED_'] = (object) array(); + $vals['_ORIGINS_'] = (object) array(); $objects = $this->importedObjects(); - $objects[$this->object_name] = $this; - $get = 'get' . $what; - $getResolved = 'getResolved' . $what; - - if ($what === 'Properties') { - $blacklist = array('id', 'object_type', 'object_name'); - } else { - $blacklist = array(); - } + $get = 'get' . $what; + $getInherited = 'getInherited' . $what; + $getOrigins = 'getOrigins' . $what; foreach ($objects as $name => $object) { - $vals[$name] = (object) array(); + $origins = $object->$getOrigins(); - if ($name === $this->object_name || $this->object_name === null) { - $pvals = $object->$get(); - } else { - $pvals = $object->$getResolved(); + foreach ($object->$getInherited() as $key => $value) { + // $vals[$name]->$key = $value; + $vals['_MERGED_']->$key = $value; + $vals['_INHERITED_']->$key = $value; + $vals['_ORIGINS_']->$key = $origins->$key; } - foreach ($pvals as $key => $value) { - if (in_array($key, $blacklist)) continue; - if ($value !== null) { - $vals[$name]->$key = $value; - $vals['_MERGED_']->$key = $value; - if ($name !== $this->object_name) { - $vals['_INHERITED_']->$key = $value; - } - } + + foreach ($object->$get() as $key => $value) { + if ($value === null) continue; + $vals['_MERGED_']->$key = $value; + $vals['_INHERITED_']->$key = $value; + $vals['_ORIGINS_']->$key = $name; } } + $blacklist = array('id', 'object_type', 'object_name'); + foreach ($this->$get() as $key => $value) { + if ($value === null) continue; + if (in_array($key, $blacklist)) continue; + + // $vals[$this->object_name]->$key = $value; + $vals['_MERGED_']->$key = $value; + } + return $vals; } From c98a687ef0e252f8328562b2ca93115d0c7a76c7 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 15:35:12 +0200 Subject: [PATCH 77/92] css/module.less: still table styles --- public/css/module.less | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/public/css/module.less b/public/css/module.less index 2837a5b1..56cb551d 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -9,21 +9,22 @@ select::-ms-expand, input::-ms-expand, textarea::-ms-expand { /* for IE 11 */ } select { - border: 1px solid transparent; + border: 1px solid #f9f9f9; cursor: pointer; } input, textarea { - border: 1px solid transparent; + border: 1px solid #f9f9f9; padding-left: 0.5em; } select:hover, input:hover, textarea:hover, select:focus, input:focus, textarea:focus { - border: 1px solid #ddd; + border: 1px solid #666; } select[value=""] { color: blue; + border: 1px solid #666; } select option { @@ -35,12 +36,6 @@ select option[value=""] { color: #aaa; } -/* TEMP */ -p.description { -display: none; -} - - ul.main-actions { margin: 0; li { @@ -259,10 +254,30 @@ table.simple { tr { padding: 0; margin: 0; + + td:first-child { + border-left: 0.5em solid transparent; + } + + td:last-child { + border-right: 0.5em solid transparent; + } + background-color: #fafcfe; } tr:nth-child(even) { - background-color: #e6e6e6; + background-color: #f6f8fa; + } + + tr:hover { + background-color: #888; + td { + color: white; + } + } + + tr.active td { + border-color: black; } th { @@ -272,7 +287,7 @@ table.simple { } td { - padding: 0.1em; + padding: 0.1em 1em; margin: 0; white-space: nowrap; } From 7b07d07d02551bc3f167799919a32b1e6c4eff3c Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 15:46:46 +0200 Subject: [PATCH 78/92] QuickForm: prepare elements before onRequest --- library/Director/Web/Form/QuickForm.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/Director/Web/Form/QuickForm.php b/library/Director/Web/Form/QuickForm.php index b2792da8..fd255233 100644 --- a/library/Director/Web/Form/QuickForm.php +++ b/library/Director/Web/Form/QuickForm.php @@ -272,8 +272,6 @@ abstract class QuickForm extends Zend_Form $this->setRequest($request); } - $this->prepareElements(); - if ($this->hasBeenSent()) { $post = $this->getRequest()->getPost(); if ($this->hasBeenSubmitted()) { @@ -366,6 +364,7 @@ abstract class QuickForm extends Zend_Form } $this->request = $request; + $this->prepareElements(); $this->onRequest(); return $this; } From cbdaf34339fb4fb7607a396ccf266fa336507200 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 15:47:18 +0200 Subject: [PATCH 79/92] DirectorDatafield, DirectorObjectForm: just lines --- library/Director/Objects/DirectorDatafield.php | 1 + library/Director/Web/Form/DirectorObjectForm.php | 1 + 2 files changed, 2 insertions(+) diff --git a/library/Director/Objects/DirectorDatafield.php b/library/Director/Objects/DirectorDatafield.php index 770587a0..ca6c2c8e 100644 --- a/library/Director/Objects/DirectorDatafield.php +++ b/library/Director/Objects/DirectorDatafield.php @@ -33,6 +33,7 @@ class DirectorDatafield extends DbObject if (! array_key_exists($key, $this->settings) || $value !== $this->settings[$key]) { $this->hasBeenModified = true; } + $this->settings[$key] = $value; return $this; } diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index dfbdb134..d2bff59a 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -383,6 +383,7 @@ abstract class DirectorObjectForm extends QuickForm { $object = $this->object(); $values = array(); + if ($this->hasBeenSent()) { $post = $this->getRequest()->getPost(); foreach ($post as $key => $value) { From c4c9980075b415749a19d08367683e78e03ddfd3 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 15:49:41 +0200 Subject: [PATCH 80/92] DirectorDatafieldForm: add a friendly note --- application/forms/DirectorDatafieldForm.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/forms/DirectorDatafieldForm.php b/application/forms/DirectorDatafieldForm.php index 57bbc170..50be4dab 100644 --- a/application/forms/DirectorDatafieldForm.php +++ b/application/forms/DirectorDatafieldForm.php @@ -9,6 +9,10 @@ class DirectorDatafieldForm extends DirectorObjectForm { public function setup() { + $this->addHtmlHint( + $this->translate('Data fields allow you to customize input controls your custom variables.') + ); + $this->addElement('text', 'varname', array( 'label' => $this->translate('Field name'), 'description' => $this->translate('The unique name of the field'), From e97f3c946a368608585347f5a2c3a989ef61c7b0 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 15:51:07 +0200 Subject: [PATCH 81/92] DirectorObjectForm: fix overrideable object name --- application/forms/DirectorDatafieldForm.php | 2 ++ library/Director/Web/Form/DirectorObjectForm.php | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/application/forms/DirectorDatafieldForm.php b/application/forms/DirectorDatafieldForm.php index 50be4dab..0f86b3c9 100644 --- a/application/forms/DirectorDatafieldForm.php +++ b/application/forms/DirectorDatafieldForm.php @@ -7,6 +7,8 @@ use Icinga\Web\Hook; class DirectorDatafieldForm extends DirectorObjectForm { + protected $objectName = 'Data field'; + public function setup() { $this->addHtmlHint( diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index d2bff59a..4f90acaa 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -12,7 +12,7 @@ abstract class DirectorObjectForm extends QuickForm protected $object; - private $objectName; + protected $objectName; private $className; @@ -321,8 +321,8 @@ abstract class DirectorObjectForm extends QuickForm $msg = sprintf( $object->hasBeenLoadedFromDb() - ? $this->translate('The Icinga %s has successfully been stored') - : $this->translate('A new Icinga %s has successfully been created'), + ? $this->translate('The %s has successfully been stored') + : $this->translate('A new %s has successfully been created'), $this->translate($this->getObjectName()) ); $object->store($this->db); From c5e0a709ad26f164ca1ea07361e4775b312e9a4a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 16:00:04 +0200 Subject: [PATCH 82/92] DirectorDatafield: fix unset/delete operation --- library/Director/Objects/DirectorDatafield.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/library/Director/Objects/DirectorDatafield.php b/library/Director/Objects/DirectorDatafield.php index ca6c2c8e..07627495 100644 --- a/library/Director/Objects/DirectorDatafield.php +++ b/library/Director/Objects/DirectorDatafield.php @@ -23,7 +23,6 @@ class DirectorDatafield extends DbObject protected $settings = array(); - public function set($key, $value) { if ($this->hasProperty($key)) { @@ -51,6 +50,20 @@ class DirectorDatafield extends DbObject return parent::get($key); } + public function __unset($key) + { + if ($this->hasProperty($key)) { + return parent::__set($key, $value); + } + + if (array_key_exists($key, $this->settings)) { + unset($this->settings[$key]); + $this->hasBeenModified = true; + } + + return $this; + } + public function getSettings() { return $this->settings; @@ -101,7 +114,7 @@ class DirectorDatafield extends DbObject } foreach ($del as $key) { - $db->update( + $db->delete( 'director_datafield_setting', $db->quoteInto($where, $key) ); From 14566620239b2f716128fc07e3a19516bd3130af Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 16:00:25 +0200 Subject: [PATCH 83/92] DirectorDatafieldForm: remove outdated settings --- application/forms/DirectorDatafieldForm.php | 53 ++++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/application/forms/DirectorDatafieldForm.php b/application/forms/DirectorDatafieldForm.php index 0f86b3c9..e6298191 100644 --- a/application/forms/DirectorDatafieldForm.php +++ b/application/forms/DirectorDatafieldForm.php @@ -23,6 +23,7 @@ class DirectorDatafieldForm extends DirectorObjectForm $this->addElement('text', 'caption', array( 'label' => $this->translate('Caption'), + 'required' => true, 'description' => $this->translate('The caption which should be displayed') )); @@ -40,12 +41,20 @@ class DirectorDatafieldForm extends DirectorObjectForm 'class' => 'autosubmit', )); - if ($class = $this->object()->datatype) { - $this->addSettings($class); - } elseif ($class = $this->getSentValue('datatype')) { + + if ($class = $this->getSentValue('datatype')) { if ($class && array_key_exists($class, $this->enumDataTypes())) { $this->addSettings($class); } + } elseif ($class = $this->object()->datatype) { + $this->addSettings($class); + } + + $this->addSettings(); + foreach ($this->object()->getSettings() as $key => $val) { + if ($el = $this->getElement($key)) { + $el->setValue($val); + } } } @@ -60,8 +69,31 @@ class DirectorDatafieldForm extends DirectorObjectForm } } + protected function clearOutdatedSettings() + { + $names = array(); + $object = $this->object(); + $global = array('varname', 'description', 'caption', 'datatype'); + + foreach ($this->getElements() as $el) { + if ($el->getIgnore()) continue; + $name = $el->getName(); + if (in_array($name, $global)) continue; + $names[$name] = $name; + } + + + foreach ($object->getSettings() as $setting => $value) { + if (! array_key_exists($setting, $names)) { + unset($object->$setting); + } + } + } + public function onSuccess() { + $this->clearOutdatedSettings(); + if ($class = $this->getValue('datatype')) { if (array_key_exists($class, $this->enumDataTypes())) { $this->addHidden('format', $class::getFormat()); @@ -71,21 +103,6 @@ class DirectorDatafieldForm extends DirectorObjectForm parent::onSuccess(); } - public function loadObject($id) - { - parent::loadObject($id); - - $this->addSettings(); - foreach ($this->object()->getSettings() as $key => $val) { - if ($el = $this->getElement($key)) { - $el->setValue($val); - } - } - $this->moveSubmitToBottom(); - - return $this; - } - protected function enumDataTypes() { $hooks = Hook::all('Director\\DataType'); From 80fe9ccc11574947b9f105058d42092d8f5770b8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 16:59:56 +0200 Subject: [PATCH 84/92] Object forms: group check execution elements --- application/forms/IcingaHostForm.php | 2 +- application/forms/IcingaServiceForm.php | 3 +-- .../Director/Web/Form/DirectorObjectForm.php | 21 ++++++++----------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/application/forms/IcingaHostForm.php b/application/forms/IcingaHostForm.php index 3620512a..e246e9ef 100644 --- a/application/forms/IcingaHostForm.php +++ b/application/forms/IcingaHostForm.php @@ -43,7 +43,7 @@ class IcingaHostForm extends DirectorObjectForm 'description' => $this->translate('Usually your hosts main IPv6 address') )); - $this->addCheckCommandElement()->addCheckFlagElements(); + $this->addCheckExecutionElements(); } else { $this->getElement('imports')->setRequired(); } diff --git a/application/forms/IcingaServiceForm.php b/application/forms/IcingaServiceForm.php index 954d4944..3f991a15 100644 --- a/application/forms/IcingaServiceForm.php +++ b/application/forms/IcingaServiceForm.php @@ -21,8 +21,7 @@ class IcingaServiceForm extends DirectorObjectForm $this->addImportsElement(); if ($this->isTemplate()) { - $this->addCheckCommandElement() - ->addCheckFlagElements(); + $this->addCheckExecutionElements(); } } } diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php index 4f90acaa..1ef09a29 100644 --- a/library/Director/Web/Form/DirectorObjectForm.php +++ b/library/Director/Web/Form/DirectorObjectForm.php @@ -464,17 +464,6 @@ abstract class DirectorObjectForm extends QuickForm return $this; } - protected function addCheckCommandElement() - { - $this->addElement('select', 'check_command_id', array( - 'label' => $this->translate('Check command'), - 'description' => $this->translate('Check command definition'), - 'multiOptions' => $this->optionalEnum($this->db->enumCheckCommands()) - )); - - return $this; - } - protected function addImportsElement() { $this->addElement('multiselect', 'imports', array( @@ -487,8 +476,16 @@ abstract class DirectorObjectForm extends QuickForm return $this; } - protected function addCheckFlagElements() + protected function addCheckExecutionElements() { + $this->addHtml('

Check execution

'); + + $this->addElement('select', 'check_command_id', array( + 'label' => $this->translate('Check command'), + 'description' => $this->translate('Check command definition'), + 'multiOptions' => $this->optionalEnum($this->db->enumCheckCommands()) + )); + $this->optionalBoolean( 'enable_active_checks', $this->translate('Execute active checks'), From 09a79014609d1a8a094723bb7deba488711c1c3a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:02:52 +0200 Subject: [PATCH 85/92] DirectorDatalistForm: one more legacy Auth Manager --- application/forms/DirectorDatalistForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/DirectorDatalistForm.php b/application/forms/DirectorDatalistForm.php index 475e23bd..452b0daa 100644 --- a/application/forms/DirectorDatalistForm.php +++ b/application/forms/DirectorDatalistForm.php @@ -3,7 +3,7 @@ namespace Icinga\Module\Director\Forms; use Icinga\Module\Director\Web\Form\DirectorObjectForm; -use Icinga\Authentication\Manager as Auth; +use Icinga\Authentication\Auth; class DirectorDatalistForm extends DirectorObjectForm { From 951cf73612ab55833f2e39516f55155e074998ca Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:13:07 +0200 Subject: [PATCH 86/92] DirectorDatalistForm: require name, remove dup --- application/forms/DirectorDatalistForm.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/application/forms/DirectorDatalistForm.php b/application/forms/DirectorDatalistForm.php index 452b0daa..4aedf76d 100644 --- a/application/forms/DirectorDatalistForm.php +++ b/application/forms/DirectorDatalistForm.php @@ -10,10 +10,9 @@ class DirectorDatalistForm extends DirectorObjectForm public function setup() { $this->addElement('text', 'list_name', array( - 'label' => $this->translate('List name') + 'label' => $this->translate('List name'), + 'required' => true, )); - - $this->addElement('hidden', 'owner'); } public function onSuccess() From d3bad2f4bb234b955415717581cd2161f29b9fde Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:19:17 +0200 Subject: [PATCH 87/92] DirectorDatalistForm: workaround no longer required --- application/forms/DirectorDatalistForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/DirectorDatalistForm.php b/application/forms/DirectorDatalistForm.php index 4aedf76d..80da505d 100644 --- a/application/forms/DirectorDatalistForm.php +++ b/application/forms/DirectorDatalistForm.php @@ -17,7 +17,7 @@ class DirectorDatalistForm extends DirectorObjectForm public function onSuccess() { - $this->addHidden('owner', self::username()); + $this->object()->owner = self::username(); parent::onSuccess(); } From c7718ebd8fd1c0b5ccdb47835d476e84886cddbc Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:25:49 +0200 Subject: [PATCH 88/92] Datalistentry: invert control --- .../controllers/DatalistentryController.php | 1 + application/forms/DirectorDatalistentryForm.php | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/application/controllers/DatalistentryController.php b/application/controllers/DatalistentryController.php index 1581d78c..5916dccc 100644 --- a/application/controllers/DatalistentryController.php +++ b/application/controllers/DatalistentryController.php @@ -40,6 +40,7 @@ class Director_DatalistentryController extends ActionController } $form = $this->view->form = $this->loadForm('directorDatalistentry') + ->setListId($listId) ->setSuccessUrl('director/datalistentry' . '?list_id=' . $listId) ->setDb($this->db()); diff --git a/application/forms/DirectorDatalistentryForm.php b/application/forms/DirectorDatalistentryForm.php index 63ee5506..2e411a4a 100644 --- a/application/forms/DirectorDatalistentryForm.php +++ b/application/forms/DirectorDatalistentryForm.php @@ -6,6 +6,8 @@ use Icinga\Module\Director\Web\Form\DirectorObjectForm; class DirectorDatalistEntryForm extends DirectorObjectForm { + protected $listId; + public function setup() { $this->addElement('text', 'entry_name', array( @@ -18,9 +20,17 @@ class DirectorDatalistEntryForm extends DirectorObjectForm 'label' => 'Type', 'multiOptions' => array('string' => $this->translate('String')) )); + } - $this->addElement('hidden', 'list_id', array( - 'value' => $this->getRequest()->getParam('list_id'), - )); + public function onSuccess() + { + $this->object()->list_id = $this->listId; + parent::onSuccess(); + } + + public function setListId($id) + { + $this->listId = $id; + return $this; } } From caa3f97048d6766d8575aa80d9c4bac1846d76cd Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:33:05 +0200 Subject: [PATCH 89/92] ObjectController: re-add object type hack --- library/Director/Web/Controller/ObjectController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Director/Web/Controller/ObjectController.php b/library/Director/Web/Controller/ObjectController.php index 0d7b077e..c7191e2c 100644 --- a/library/Director/Web/Controller/ObjectController.php +++ b/library/Director/Web/Controller/ObjectController.php @@ -95,6 +95,7 @@ abstract class ObjectController extends ActionController if ($object->isTemplate()) { $title = $this->translate('Modify Icinga %s template'); + $form->setObjectType('template'); // WHY?? } else { $title = $this->translate('Modify Icinga %s'); } From b265f48a890c501cfee31133c52c23fea59f53cc Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:34:12 +0200 Subject: [PATCH 90/92] IcingaService: make use of fields --- library/Director/Objects/IcingaObject.php | 2 +- library/Director/Objects/IcingaService.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index 89d53cf6..40f2047e 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -377,7 +377,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer array('f' => $this->getTableName() . '_field'), 'df.id = f.datafield_id', array() - )->where('f.host_id = ?', (int) $this->id) + )->where('f.' . $this->getShortTableName() . '_id = ?', (int) $this->id) ->order('df.caption ASC'); $res = $db->fetchAll($query); diff --git a/library/Director/Objects/IcingaService.php b/library/Director/Objects/IcingaService.php index b6aa6a20..1c92d25f 100644 --- a/library/Director/Objects/IcingaService.php +++ b/library/Director/Objects/IcingaService.php @@ -38,6 +38,8 @@ class IcingaService extends IcingaObject protected $supportsCustomVars = true; + protected $supportsFields = true; + protected $supportsImports = true; protected function renderCheck_command_id() From 1c305eaa79bfa5f7d2982a97fab8a9547da40ce8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:34:37 +0200 Subject: [PATCH 91/92] css/module.less: hide descriptions for now --- public/css/module.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/css/module.less b/public/css/module.less index 56cb551d..e663a858 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -1,3 +1,7 @@ +form p.description { + display: none; +} + input, select, select option, textarea { -webkit-appearance: none; -moz-appearance: none; From 26cc2e4eacb6f51f9946d3c93ca6d674abccfd42 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 31 Jul 2015 17:36:00 +0200 Subject: [PATCH 92/92] IcingaHost/ServiceForm: temporarily disable groups --- application/forms/IcingaHostForm.php | 2 ++ application/forms/IcingaServiceForm.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/application/forms/IcingaHostForm.php b/application/forms/IcingaHostForm.php index e246e9ef..5d7dc6be 100644 --- a/application/forms/IcingaHostForm.php +++ b/application/forms/IcingaHostForm.php @@ -27,10 +27,12 @@ class IcingaHostForm extends DirectorObjectForm $this->addImportsElement(); + /* $this->addElement('text', 'groups', array( 'label' => $this->translate('Hostgroups'), 'description' => $this->translate('One or more comma separated hostgroup names') )); + */ if ($this->isTemplate()) { $this->addElement('text', 'address', array( diff --git a/application/forms/IcingaServiceForm.php b/application/forms/IcingaServiceForm.php index 3f991a15..5f94f814 100644 --- a/application/forms/IcingaServiceForm.php +++ b/application/forms/IcingaServiceForm.php @@ -14,10 +14,13 @@ class IcingaServiceForm extends DirectorObjectForm 'description' => $this->translate('Name for the Icinga object you are going to create') )); + /* $this->addElement('text', 'groups', array( 'label' => $this->translate('Servicegroups'), 'description' => $this->translate('One or more comma separated servicegroup names') )); + */ + $this->addImportsElement(); if ($this->isTemplate()) {