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-03-25 07:01:32 -04:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Icinga\Module\Director\Forms;
|
|
|
|
|
|
|
|
|
|
use Icinga\Module\Director\Data\Db\DbObjectTypeRegistry;
|
2026-03-25 12:03:21 -04:00
|
|
|
use Icinga\Module\Director\Db\DbUtil;
|
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-03-25 07:01:32 -04:00
|
|
|
use Icinga\Module\Director\Forms\DictionaryElements\Dictionary;
|
2026-05-12 05:12:35 -04:00
|
|
|
use Icinga\Module\Director\Forms\DictionaryElements\DictionaryItem;
|
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-03-25 07:01:32 -04:00
|
|
|
use Icinga\Module\Director\Objects\DirectorActivityLog;
|
|
|
|
|
use Icinga\Module\Director\Objects\IcingaHost;
|
|
|
|
|
use Icinga\Module\Director\Objects\IcingaObject;
|
|
|
|
|
use Icinga\Module\Director\Objects\IcingaService;
|
|
|
|
|
use Icinga\Module\Director\Objects\IcingaServiceSet;
|
|
|
|
|
use Icinga\Web\Session;
|
|
|
|
|
use ipl\Html\Attributes;
|
2026-05-12 05:12:35 -04:00
|
|
|
use ipl\Html\BaseHtmlElement;
|
|
|
|
|
use ipl\Html\Html;
|
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-03-25 07:01:32 -04:00
|
|
|
use ipl\Html\HtmlElement;
|
|
|
|
|
use ipl\Html\Text;
|
|
|
|
|
use ipl\I18n\Translation;
|
|
|
|
|
use ipl\Web\Common\CsrfCounterMeasure;
|
|
|
|
|
use ipl\Web\Compat\CompatForm;
|
|
|
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
|
|
|
|
|
|
class CustomVariablesForm extends CompatForm
|
|
|
|
|
{
|
|
|
|
|
use CsrfCounterMeasure;
|
|
|
|
|
use Translation;
|
|
|
|
|
|
|
|
|
|
private ?IcingaService $applyGenerated = null;
|
|
|
|
|
|
|
|
|
|
private ?string $inheritedServiceFrom = null;
|
|
|
|
|
|
|
|
|
|
private ?IcingaServiceSet $set = null;
|
|
|
|
|
|
|
|
|
|
private ?IcingaHost $host = null;
|
|
|
|
|
|
|
|
|
|
private bool $varsHasBeenModified = false;
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
private array $addedVarUuids = [];
|
|
|
|
|
|
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-03-25 07:01:32 -04:00
|
|
|
public function __construct(
|
|
|
|
|
public readonly IcingaObject $object,
|
|
|
|
|
protected array $objectProperties = []
|
|
|
|
|
) {
|
|
|
|
|
$this->addAttributes(Attributes::create(['class' => 'custom-variables-form']));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if the custom properties have been modified
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function varsHasBeenModified(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->varsHasBeenModified;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
public function setAddedVarUuids(array $uuids): static
|
|
|
|
|
{
|
|
|
|
|
$this->addedVarUuids = $uuids;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
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-03-25 07:01:32 -04:00
|
|
|
protected function assemble(): void
|
|
|
|
|
{
|
|
|
|
|
$this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId()));
|
|
|
|
|
$dictionary = (new Dictionary(
|
|
|
|
|
'properties',
|
|
|
|
|
$this->objectProperties,
|
|
|
|
|
['class' => 'no-border']
|
|
|
|
|
))->setAllowItemRemoval($this->object->isTemplate());
|
|
|
|
|
|
|
|
|
|
$saveButton = $this->createElement('submit', 'save', [
|
|
|
|
|
'label' => $this->isOverrideServiceVars()
|
|
|
|
|
? $this->translate('Override Custom Variables')
|
|
|
|
|
: $this->translate('Save Custom Variables')
|
|
|
|
|
]);
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
$addedUuidsContainer = new HtmlElement(
|
|
|
|
|
'div',
|
|
|
|
|
Attributes::create(['id' => 'added-var-uuids', 'class' => 'added-var-uuids', 'tabindex' => -1])
|
|
|
|
|
);
|
|
|
|
|
|
2026-05-12 07:22:25 -04:00
|
|
|
$addedUuidsElement = $this->createElement(
|
|
|
|
|
'hidden',
|
|
|
|
|
'addedVarUuids',
|
|
|
|
|
[
|
|
|
|
|
'value' => implode(',', $this->addedVarUuids)
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->registerElement($addedUuidsElement);
|
|
|
|
|
$addedUuidsContainer->addHtml($addedUuidsElement);
|
2026-05-12 05:12:35 -04:00
|
|
|
|
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-03-25 07:01:32 -04:00
|
|
|
$this->addElement($this->duplicateSubmitButton($saveButton));
|
|
|
|
|
$this->addElement($dictionary);
|
|
|
|
|
if ($this->hasBeenSent()) {
|
|
|
|
|
$dictionary->ensureAssembled();
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
$this->addHtml($addedUuidsContainer);
|
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-03-25 07:01:32 -04:00
|
|
|
$this->registerElement($saveButton);
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
$removedItems = $dictionary->getItemsToRemove();
|
2026-05-12 07:22:25 -04:00
|
|
|
$removedUuids = [];
|
|
|
|
|
foreach ($removedItems as $removedItem) {
|
|
|
|
|
$removedUuids[] = Uuid::fromBytes($this->objectProperties[$removedItem]['uuid'])->toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$removedUuids = array_diff($removedUuids, $this->addedVarUuids);
|
|
|
|
|
|
|
|
|
|
if (! empty($removedUuids)) {
|
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-03-25 07:01:32 -04:00
|
|
|
$this->addHtml(
|
|
|
|
|
new HtmlElement('div', Attributes::create(['class' => 'message']), Text::create(
|
|
|
|
|
sprintf(
|
|
|
|
|
$this->translatePlural(
|
|
|
|
|
'(%d) property has been removed',
|
|
|
|
|
'(%d) properties have been removed',
|
2026-05-12 07:22:25 -04:00
|
|
|
count($removedUuids)
|
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-03-25 07:01:32 -04:00
|
|
|
),
|
2026-05-12 07:22:25 -04:00
|
|
|
count($removedUuids)
|
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-03-25 07:01:32 -04:00
|
|
|
)
|
|
|
|
|
))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->addElement($saveButton);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the applied rule from where the custom variables are inherited from
|
|
|
|
|
*
|
|
|
|
|
* @param IcingaService $applyGenerated
|
|
|
|
|
*
|
|
|
|
|
* @return $this
|
|
|
|
|
*/
|
|
|
|
|
public function setApplyGenerated(IcingaService $applyGenerated): static
|
|
|
|
|
{
|
|
|
|
|
$this->applyGenerated = $applyGenerated;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setInheritedServiceFrom(string $hostname): static
|
|
|
|
|
{
|
|
|
|
|
$this->inheritedServiceFrom = $hostname;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the service set from where the custom variables are inherited from
|
|
|
|
|
*
|
|
|
|
|
* @param IcingaServiceSet $set
|
|
|
|
|
*
|
|
|
|
|
* @return $this
|
|
|
|
|
*/
|
|
|
|
|
public function setServiceSet(IcingaServiceSet $set): static
|
|
|
|
|
{
|
|
|
|
|
$this->set = $set;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set host if the object is a service
|
|
|
|
|
*
|
|
|
|
|
* @param IcingaHost $host
|
|
|
|
|
*
|
|
|
|
|
* @return $this
|
|
|
|
|
*/
|
|
|
|
|
public function setHostForService(IcingaHost $host): static
|
|
|
|
|
{
|
|
|
|
|
$this->host = $host;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Are the populated values for custom properties a part of _override_servicevars
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function isOverrideServiceVars(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->applyGenerated
|
|
|
|
|
|| $this->inheritedServiceFrom
|
|
|
|
|
|| ($this->host && $this->set);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function hasBeenSubmitted(): bool
|
|
|
|
|
{
|
|
|
|
|
$pressedButton = $this->getPressedSubmitElement();
|
|
|
|
|
|
|
|
|
|
if ($pressedButton && $pressedButton->getName() === 'save') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load form with object properties
|
|
|
|
|
*
|
|
|
|
|
* @param array $objectProperties
|
|
|
|
|
*
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function load(array $objectProperties): void
|
|
|
|
|
{
|
|
|
|
|
$this->populate([
|
|
|
|
|
'properties' => Dictionary::prepare($objectProperties)
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 05:12:35 -04:00
|
|
|
/**
|
|
|
|
|
* Build a standalone DictionaryItem row for use in a multipart update.
|
|
|
|
|
*
|
|
|
|
|
* @param array $propertyData Row data as returned by getObjectCustomProperties()
|
|
|
|
|
* @param int $index The slot index this item occupies
|
|
|
|
|
*
|
|
|
|
|
* @return BaseHtmlElement
|
|
|
|
|
*/
|
|
|
|
|
public function prepareNewPropertyRow(array $propertyData, int $index): BaseHtmlElement
|
|
|
|
|
{
|
|
|
|
|
$this->ensureAssembled();
|
|
|
|
|
/** @var Dictionary $dictionary */
|
|
|
|
|
$dictionary = $this->getElement('properties');
|
|
|
|
|
|
|
|
|
|
if ($propertyData['allow_removal']) {
|
|
|
|
|
$removeButton = $dictionary->createElement('submitButton', 'remove_' . $index, [
|
|
|
|
|
'label' => 'Remove Item',
|
|
|
|
|
'class' => ['remove-property'],
|
|
|
|
|
'formnovalidate' => true
|
|
|
|
|
]);
|
|
|
|
|
$dictionary->registerElement($removeButton);
|
|
|
|
|
} else {
|
|
|
|
|
$removeButton = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$propertyData['uuid'] = DbUtil::binaryResult($propertyData['uuid']);
|
|
|
|
|
$newItem = new DictionaryItem((string) $index, $propertyData);
|
|
|
|
|
|
|
|
|
|
$this->decorate($newItem);
|
|
|
|
|
if ($removeButton !== null) {
|
|
|
|
|
$newItem->setRemoveButton($removeButton);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dictionary->registerElement($newItem);
|
|
|
|
|
|
|
|
|
|
$newItem->populate(DictionaryItem::prepare($propertyData));
|
|
|
|
|
|
|
|
|
|
return $newItem;
|
|
|
|
|
}
|
|
|
|
|
|
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-03-25 07:01:32 -04:00
|
|
|
/**
|
|
|
|
|
* Filter empty values from array
|
|
|
|
|
*
|
|
|
|
|
* @param array $array
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function filterEmpty(array $array): array
|
|
|
|
|
{
|
|
|
|
|
return array_filter(
|
|
|
|
|
array_map(function ($item) {
|
|
|
|
|
if (! is_array($item)) {
|
|
|
|
|
// Recursively clean nested arrays
|
|
|
|
|
return $item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return self::filterEmpty($item);
|
|
|
|
|
}, $array),
|
|
|
|
|
function ($item) {
|
|
|
|
|
return is_bool($item) || ! empty($item);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function onSuccess(): void
|
|
|
|
|
{
|
|
|
|
|
$vars = $this->object->vars();
|
|
|
|
|
|
|
|
|
|
/** @var Dictionary $propertiesElement */
|
|
|
|
|
$propertiesElement = $this->getElement('properties');
|
|
|
|
|
$values = $propertiesElement->getDictionary();
|
|
|
|
|
$itemsToRemove = $propertiesElement->getItemsToRemove();
|
|
|
|
|
$type = $this->object->getShortTableName();
|
2026-03-25 12:03:21 -04:00
|
|
|
$db = $this->object->getDb();
|
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-03-25 07:01:32 -04:00
|
|
|
foreach ($this->objectProperties as $key => $property) {
|
|
|
|
|
$propertyUuid = Uuid::fromBytes($property['uuid']);
|
|
|
|
|
if (isset($property['removed'])) {
|
|
|
|
|
$itemsToRemoveUuids[] = $property['uuid'];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (in_array($key, $itemsToRemove)) {
|
|
|
|
|
$itemsToRemoveUuids[] = $property['uuid'];
|
|
|
|
|
$this->varsHasBeenModified = true;
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$value = $values[$key] ?? null;
|
|
|
|
|
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
|
$filteredValue = self::filterEmpty($value);
|
|
|
|
|
// Store the fixed array as empty only if the filtered array is empty
|
|
|
|
|
if ($property['value_type'] !== 'fixed-array' || empty($filteredValue)) {
|
|
|
|
|
$value = $filteredValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($property['new'])) {
|
2026-05-15 07:36:05 -04:00
|
|
|
$this->varsHasBeenModified = true;
|
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-03-25 07:01:32 -04:00
|
|
|
$this->object->getConnection()->insert(
|
|
|
|
|
"icinga_$type" . '_property',
|
|
|
|
|
[
|
2026-03-25 12:03:21 -04:00
|
|
|
$type . '_uuid' => DbUtil::quoteBinaryCompat($this->object->uuid, $db),
|
|
|
|
|
'property_uuid' => DbUtil::quoteBinaryCompat($propertyUuid->getBytes(), $db)
|
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-03-25 07:01:32 -04:00
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! is_bool($value) && empty($value)) {
|
|
|
|
|
$vars->set($key, null);
|
|
|
|
|
} else {
|
|
|
|
|
$vars->set($key, $value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($vars->get($key) && $vars->get($key)->getUuid() === null && isset($property['uuid'])) {
|
|
|
|
|
$vars->registerVarUuid($key, $propertyUuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->varsHasBeenModified === false && $vars->hasBeenModified()) {
|
|
|
|
|
$this->varsHasBeenModified = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! empty($itemsToRemove)) {
|
|
|
|
|
$objectId = (int) $this->object->get('id');
|
|
|
|
|
$db = $this->object->getDb();
|
|
|
|
|
|
|
|
|
|
$objectsToCleanUp = [$objectId];
|
|
|
|
|
$propertyAsObjectVar = $db->fetchAll(
|
|
|
|
|
$db
|
|
|
|
|
->select()
|
|
|
|
|
->from('icinga_' . $type . '_var')
|
2026-03-25 12:03:21 -04:00
|
|
|
->where('property_uuid IN (?)', DbUtil::quoteBinaryCompat($itemsToRemoveUuids, $db))
|
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-03-25 07:01:32 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
foreach ($propertyAsObjectVar as $propertyAsObjectVarRow) {
|
|
|
|
|
$class = DbObjectTypeRegistry::classByType($type);
|
|
|
|
|
$object = $class::loadWithAutoIncId(
|
|
|
|
|
$propertyAsObjectVarRow->{$type . '_id'},
|
|
|
|
|
$this->object->getConnection()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (in_array($objectId, $object->listAncestorIds(), true)) {
|
|
|
|
|
$objectsToCleanUp[] = (int) $object->get('id');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$propertyWhere = $this->object->getDb()->quoteInto('property_uuid IN (?)', $itemsToRemoveUuids);
|
|
|
|
|
$objectsWhere = $this->object->getDb()->quoteInto($type . '_id IN (?)', $objectsToCleanUp);
|
|
|
|
|
$db->delete('icinga_' . $type . '_var', $propertyWhere . ' AND ' . $objectsWhere);
|
|
|
|
|
|
|
|
|
|
$objectWhere = $this->object->getDb()->quoteInto($type . '_uuid = ?', $this->object->get('uuid'));
|
|
|
|
|
$db->delete(
|
|
|
|
|
'icinga_' . $type . '_property',
|
|
|
|
|
$propertyWhere . ' AND ' . $objectWhere
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->isOverrideServiceVars()) {
|
|
|
|
|
$object = $this->host;
|
|
|
|
|
$overrideVars = (array) $this->host->getOverriddenServiceVars($this->object->getObjectName());
|
|
|
|
|
foreach ($vars as $varName => $var) {
|
|
|
|
|
if ($var->hasBeenModified()) {
|
|
|
|
|
$overrideVars[$varName] = $var->getValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$object->overrideServiceVars($this->object->getObjectName(), (object) $overrideVars);
|
|
|
|
|
DirectorActivityLog::logModification($object, $this->object->getConnection());
|
|
|
|
|
|
|
|
|
|
$object->store($this->object->getConnection());
|
|
|
|
|
} else {
|
|
|
|
|
$object = $this->object;
|
|
|
|
|
DirectorActivityLog::logModification($object, $this->object->getConnection());
|
|
|
|
|
$vars->storeToDb($object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|