From 88e2ca26aca36c4da1a1ae38860b62102d3d9f48 Mon Sep 17 00:00:00 2001 From: raviks789 Date: Wed, 2 Oct 2024 10:00:47 +0200 Subject: [PATCH] Show affected objects in the object detail for failed dependencies --- library/Icingadb/Widget/Detail/HostDetail.php | 1 + .../Icingadb/Widget/Detail/ObjectDetail.php | 94 +++++++++++++++++++ .../Icingadb/Widget/Detail/ServiceDetail.php | 1 + 3 files changed, 96 insertions(+) diff --git a/library/Icingadb/Widget/Detail/HostDetail.php b/library/Icingadb/Widget/Detail/HostDetail.php index 969b37ffb..17e1ab565 100644 --- a/library/Icingadb/Widget/Detail/HostDetail.php +++ b/library/Icingadb/Widget/Detail/HostDetail.php @@ -50,6 +50,7 @@ protected function assemble() 401 => $this->createDowntimes(), 500 => $this->createGroups(), 501 => $this->createNotifications(), + 510 => $this->createAffectedObjects(), 600 => $this->createCheckStatistics(), 601 => $this->createPerformanceData(), 700 => $this->createCustomVars(), diff --git a/library/Icingadb/Widget/Detail/ObjectDetail.php b/library/Icingadb/Widget/Detail/ObjectDetail.php index 9a95f297d..489cd306b 100644 --- a/library/Icingadb/Widget/Detail/ObjectDetail.php +++ b/library/Icingadb/Widget/Detail/ObjectDetail.php @@ -21,6 +21,7 @@ use Icinga\Module\Icingadb\Common\Macros; use Icinga\Module\Icingadb\Compat\CompatHost; use Icinga\Module\Icingadb\Model\CustomvarFlat; +use Icinga\Module\Icingadb\Model\DependencyNode; use Icinga\Module\Icingadb\Model\Service; use Icinga\Module\Icingadb\Model\UnreachableParent; use Icinga\Module\Icingadb\Web\Navigation\Action; @@ -36,6 +37,7 @@ use Icinga\Module\Icingadb\Util\PluginOutput; use Icinga\Module\Icingadb\Widget\ItemList\DowntimeList; use Icinga\Module\Icingadb\Widget\ShowMore; +use ipl\Sql\Select; use ipl\Web\Widget\CopyToClipboard; use ipl\Web\Widget\EmptyState; use ipl\Web\Widget\HorizontalKeyValue; @@ -648,4 +650,96 @@ protected function createRootProblems(): ?array new DependencyNodeList($rootProblems) ]; } + + protected function createAffectedObjects() + { + if (! $this->object->state->affects_children) { + return null; + } + + $affectedObjects = DependencyNode::on($this->getDb()) + ->with([ + 'redundancy_group', + 'redundancy_group.state', + 'host', + 'host.state', + 'host.icon_image', + 'host.state.last_comment', + 'service', + 'service.state', + 'service.icon_image', + 'service.state.last_comment', + 'service.host', + 'service.host.state' + ])->orderBy([ + 'host.state.severity' => SORT_DESC, + 'host.state.last_state_change' => SORT_DESC, + 'service.state.severity' => SORT_DESC, + 'service.state.last_state_change' => SORT_DESC, + 'service.host.state.severity' => SORT_DESC, + 'service.host.state.last_state_change' => SORT_DESC, + 'redundancy_group.state.last_state_change' => SORT_DESC + ]); + + if ($this->object instanceof Host) { + $affectedObjects + ->filter(Filter::equal('parent.host.id', $this->object->id)) + //TODO: only workaround, remove once https://github.com/Icinga/ipl-orm/issues/76#issuecomment-2370629031 + // is fixed + ->on($affectedObjects::ON_SELECT_ASSEMBLED, function (Select $select) { + $subQuery = $select->getWhere()[1][0][1][0][1]['dependency_node.id IN (?)']; + $select->resetWhere(); + + $joins = $subQuery->getJoin(); + $subQuery->resetJoin(); + + foreach ($joins as $join) { + $condition = $join[2]; + if ($condition[1][0] === 'sub_host_dependency_node.host_id = sub_host.id') { + $condition[1][0] = sprintf( + '%s AND sub_host_dependency_node.service_id IS NULL', + $condition[1][0] + ); + } + + $subQuery->join($join[1], $condition); + } + + $select->where(['dependency_node.id IN (?)' => $subQuery]); + }); + } else { + $affectedObjects + ->filter(Filter::equal('parent.service.id', $this->object->id)) + //TODO: only workaround, remove once https://github.com/Icinga/ipl-orm/issues/76#issuecomment-2370629031 + // is fixed + ->on($affectedObjects::ON_SELECT_ASSEMBLED, function (Select $select) { + $subQuery = $select->getWhere()[1][0][1][0][1]['dependency_node.id IN (?)']; + $select->resetWhere(); + + $joins = $subQuery->getJoin(); + $subQuery->resetJoin(); + + foreach ($joins as $join) { + $condition = $join[2]; + if ($condition[1][0] === 'sub_service_dependency_node.service_id = sub_service.id') { + $condition[1][0] = sprintf( + '%s AND sub_service_dependency_node.host_id = sub_service.host_id', + $condition[1][0] + ); + } + + $subQuery->join($join[1], $condition); + } + + $select->where(['dependency_node.id IN (?)' => $subQuery]); + }); + } + + $this->applyRestrictions($affectedObjects); + + return [ + HtmlElement::create('h2', null, Text::create(t('Affected Objects'))), + new DependencyNodeList($affectedObjects) + ]; + } } diff --git a/library/Icingadb/Widget/Detail/ServiceDetail.php b/library/Icingadb/Widget/Detail/ServiceDetail.php index 86e7651ff..613e31e8b 100644 --- a/library/Icingadb/Widget/Detail/ServiceDetail.php +++ b/library/Icingadb/Widget/Detail/ServiceDetail.php @@ -29,6 +29,7 @@ protected function assemble() 401 => $this->createDowntimes(), 500 => $this->createGroups(), 501 => $this->createNotifications(), + 510 => $this->createAffectedObjects(), 600 => $this->createCheckStatistics(), 601 => $this->createPerformanceData(), 700 => $this->createCustomVars(),