icingaweb2-module-director/application/controllers/SuggestionsController.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

69 lines
2.3 KiB
PHP

<?php
namespace Icinga\Module\Director\Controllers;
use Icinga\Application\Config;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Director\Db;
use ipl\Stdlib\Filter as iplFilter;
use ipl\Web\Compat\CompatController;
use ipl\Web\Filter\QueryString;
use ipl\Web\FormElement\SearchSuggestions;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
class SuggestionsController extends CompatController
{
/** @var Db */
protected $db;
/** @var UuidInterface */
private UuidInterface $uuid;
public function datalistEntryAction(): void
{
$excludes = iplFilter::none();
$uuid = Uuid::fromString($this->params->shiftRequired('uuid'));
$this->db = Db::fromResourceName(
Config::module('director')->get('db', 'resource')
);
$excludeTerms = [];
if ($this->params->has('exclude')) {
$excludeTerms = explode(',', $this->params->get('exclude'));
}
if (! empty($excludeTerms)) {
foreach ($excludeTerms as $excludeTerm) {
$excludes->add(iplFilter::equal('entry_name', $excludeTerm));
}
}
$suggestions = new SearchSuggestions((function () use ($uuid, $excludes, &$suggestions) {
foreach ($suggestions->getExcludeTerms() as $excludeTerm) {
$excludes->add(iplFilter::equal('entry_name', $excludeTerm));
}
$query = $this->db->select()->from(['dle' => 'director_datalist_entry'], ['entry_name', 'entry_value'])
->join(['dl' => 'director_datalist'], 'dl.id = dle.list_id', [])
->join(['dpl' => 'director_property_datalist'], 'dl.uuid = dpl.list_uuid', [])
->where('dpl.property_uuid', $uuid->getBytes());
$filterString = QueryString::render(iplFilter::all($excludes));
if ($filterString !== '') {
$query->addFilter(Filter::fromQueryString($filterString));
}
foreach ($this->db->fetchPairs($query) as $name => $value) {
yield [
'search' => $name,
'label' => $value,
'class' => 'list-entry'
];
}
})());
$this->getDocument()->addHtml($suggestions->forRequest($this->getServerRequest()));
}
}