From 3e4e00c8afdd38ae93e672c7ea62df9264011d64 Mon Sep 17 00:00:00 2001 From: raviks789 Date: Tue, 27 May 2025 13:27:40 +0200 Subject: [PATCH] Render the host dictionary items as variable in apply-for-rule --- .../CustomVariable/CustomVariableString.php | 28 +++++---- .../CustomVariable/CustomVariables.php | 18 ++++++ library/Director/Objects/IcingaService.php | 61 +++++++++++++++++++ 3 files changed, 96 insertions(+), 11 deletions(-) diff --git a/library/Director/CustomVariable/CustomVariableString.php b/library/Director/CustomVariable/CustomVariableString.php index e4012da8..88e23895 100644 --- a/library/Director/CustomVariable/CustomVariableString.php +++ b/library/Director/CustomVariable/CustomVariableString.php @@ -7,6 +7,15 @@ use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1; class CustomVariableString extends CustomVariable { + private $whiteList = []; + + protected function __construct($key, $value = null, $whiteList = []) + { + parent::__construct($key, $value); + + $this->whiteList = $whiteList; + } + public function equals(CustomVariable $var) { if (! $var instanceof CustomVariableString) { @@ -46,17 +55,7 @@ class CustomVariableString extends CustomVariable public function toConfigString($renderExpressions = false) { if ($renderExpressions) { - $whiteList = ['value']; - $value = $this->getValue(); - if ( - str_starts_with($value, '$') - && str_ends_with($value, '$') - && str_contains($value, 'value.') - ) { - $whiteList[] = trim($value, '$'); - } - - return c::renderStringWithVariables($this->getValue(), $whiteList); + return c::renderStringWithVariables($this->getValue(), $this->whiteList); } else { return c::renderString($this->getValue()); } @@ -66,4 +65,11 @@ class CustomVariableString extends CustomVariable { return c1::renderString($this->getValue()); } + + public function setWhiteList(array $whiteList): self + { + $this->whiteList = $whiteList; + + return $this; + } } diff --git a/library/Director/CustomVariable/CustomVariables.php b/library/Director/CustomVariable/CustomVariables.php index bb0b44b3..7fc0b408 100644 --- a/library/Director/CustomVariable/CustomVariables.php +++ b/library/Director/CustomVariable/CustomVariables.php @@ -27,6 +27,8 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer protected $idx = array(); + private $whiteList = []; + protected static $allTables = array( 'icinga_command_var', 'icinga_host_var', @@ -159,6 +161,18 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer return $this; } + public function setWhiteList(array $whitelist): self + { + $this->whiteList = $whitelist; + + return $this; + } + + public function getWhiteList(array $whitelist): array + { + return $this->whiteList; + } + protected function refreshIndex() { $this->idx = array(); @@ -398,6 +412,10 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer */ protected function renderSingleVar($key, $var, $renderExpressions = false) { + if ($var instanceof CustomVariableString) { + $var->setWhiteList($this->whiteList); + } + if ($key === $this->overrideKeyName) { return c::renderKeyOperatorValue( $this->renderKeyName($key), diff --git a/library/Director/Objects/IcingaService.php b/library/Director/Objects/IcingaService.php index d0dfd1a6..8b66c0d8 100644 --- a/library/Director/Objects/IcingaService.php +++ b/library/Director/Objects/IcingaService.php @@ -14,6 +14,7 @@ use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1; use Icinga\Module\Director\Objects\Extension\FlappingSupport; use Icinga\Module\Director\Resolver\HostServiceBlacklist; use InvalidArgumentException; +use PDO; use RuntimeException; class IcingaService extends IcingaObject implements ExportInterface @@ -24,6 +25,8 @@ class IcingaService extends IcingaObject implements ExportInterface protected $uuidColumn = 'uuid'; + private $vars; + protected $defaultProperties = [ 'id' => null, 'uuid' => null, @@ -660,6 +663,64 @@ class IcingaService extends IcingaObject implements ExportInterface return $where; } + public function vars() + { + $vars = parent::vars(); + + if ($this->isApplyRule() && $vars) { + $applyFor = substr($this->get('apply_for'), strlen('host.vars.')); + $query = $this->db + ->select() + ->from( + ['dp' => 'director_property'], + [ + 'key_name' => 'dp.key_name', + 'uuid' => 'dp.uuid', + 'value_type' => 'dp.value_type' + ] + ) + ->join(['parent_dp' => 'director_property'], 'dp.parent_uuid = parent_dp.uuid', []) + ->where("parent_dp.value_type = 'dict'") + ->where("parent_dp.key_name = ?", $applyFor); + + $result = $this->db->fetchAll($query, fetchMode: PDO::FETCH_ASSOC); + + $whiteList = ['$value$']; + foreach ($result as $row) { + $whiteList[] = sprintf('value.%s', $row['key_name']); + + if ($row['value_type'] === 'dict') { + foreach ($this->fetchItemsForDictionary($row['uuid']) as $value) { + $whiteList[] = sprintf('value.%s.%s', $row['key_name'], $value['key_name']); + } + } + } + + + $vars->setWhiteList($whiteList); + } + + return $vars; + } + + protected function fetchItemsForDictionary(string $uuid): array + { + $query = $this->db + ->select() + ->from( + ['dp' => 'director_property'], + [ + 'key_name' => 'dp.key_name', + 'uuid' => 'dp.uuid', + 'value_type' => 'dp.value_type', + ] + ) + ->join(['parent_dp' => 'director_property'], 'dp.parent_uuid = parent_dp.uuid', []) + ->where("dp.parent_uuid = ?", $uuid); + + return $this->db->fetchAll($query, fetchMode: PDO::FETCH_ASSOC); + } + /** * TODO: Duplicate code, clean this up, split it into multiple methods