icingaweb2-module-director/application/controllers/VariablesController.php
Ravi Srinivasa 6198cd8d9b
Alternative custom property support with dictionary handling
Introduce a first-class DirectorProperty concept that extends the existing
data-fields model with rich, structured variable types. Custom variables can
now be defined globally under a new "Custom Variables" section and assigned
to Icinga objects (hosts, services, commands, etc.).

Supported types: string, number, boolean, fixed-array, dynamic-array,
datalist-strict, datalist-non-strict, fixed-dictionary, and
dynamic-dictionary (one level of nesting allowed).

Key changes:
  - DirectorProperty object with CRUD, inheritance, and apply-for rule support
  - New form elements: Dictionary, DictionaryItem, NestedDictionary,
    NestedDictionaryItem, ArrayElement, IplBoolean
  - CustomvarController for managing global property definitions
  - VariablesController for per-object variable assignment
  - BasketSnapshotCustomVariableResolver for basket import/export of properties
  - REST API: IcingaObjectHandler extended to expose and accept structured vars
  - IcingaConfigHelper: renders dictionaries/arrays to valid Icinga 2 DSL
  - CustomVarRenderer updated for icingadb hook display
  - DB migration upgrade_192.sql: new director_property and related tables
  - CLI: MigrateCommand for migrating legacy vars to properties;
    HostsCommand for bulk host custom variable management
2026-05-15 13:41:00 +02:00

83 lines
3 KiB
PHP

<?php
namespace Icinga\Module\Director\Controllers;
use Icinga\Application\Config;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Forms\CustomVariableForm;
use Icinga\Module\Director\Web\Widget\CustomVarFieldsTable;
use Icinga\Web\Notification;
use ipl\Html\Html;
use ipl\Html\Text;
use ipl\Web\Compat\CompatController;
use ipl\Web\Url;
use ipl\Web\Widget\ButtonLink;
class VariablesController extends CompatController
{
public function indexAction()
{
$this->addTitleTab($this->translate('Custom Variables'));
$db = Db::fromResourceName(
Config::module('director')->get('db', 'resource')
)->getDbAdapter();
$query = $db->select()
->from(['dp' => 'director_property'], [])
->joinLeft(['ihp' => 'icinga_host_property'], 'ihp.property_uuid = dp.uuid', [])
->joinLeft(['isp' => 'icinga_service_property'], 'isp.property_uuid = dp.uuid', [])
->joinLeft(['iup' => 'icinga_user_property'], 'isp.property_uuid = dp.uuid', [])
->joinLeft(['icp' => 'icinga_command_property'], 'isp.property_uuid = dp.uuid', [])
->joinLeft(['inp' => 'icinga_notification_property'], 'isp.property_uuid = dp.uuid', [])
->columns([
'key_name',
'uuid',
'parent_uuid',
'value_type',
'label',
'description',
'used_count' => 'COUNT(ihp.property_uuid) + COUNT(isp.property_uuid)'
. ' + COUNT(iup.property_uuid) + COUNT(icp.property_uuid) + COUNT(inp.property_uuid)'
])
->where('parent_uuid IS NULL')
->group('dp.uuid')
->order('key_name');
$properties = new CustomVarFieldsTable($db->fetchAll($query));
$this->addControl(Html::tag('div', ['class' => 'custom-variable-form'], [
(new ButtonLink(
[Text::create($this->translate('Create Custom Variable'))],
Url::fromPath('director/variables/add'),
null,
[
'class' => 'control-button'
]
))->setBaseTarget('_next')
]));
$this->addContent($properties);
}
public function addAction()
{
$this->addTitleTab($this->translate('Create Custom Variable'));
$db = Db::fromResourceName(
Config::module('director')->get('db', 'resource')
);
$propertyForm = (new CustomVariableForm($db))
->on(CustomVariableForm::ON_SUBMIT, function (CustomVariableForm $form) {
Notification::success(sprintf(
$this->translate('Property "%s" has successfully been added'),
$form->getValue('key_name')
));
$this->redirectNow(Url::fromPath('director/customvar', ['uuid' => $form->getUUid()->toString()]));
})
->handleRequest($this->getServerRequest());
$this->addContent($propertyForm);
}
}