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 35c017bc6..064fb1f02 100644 --- a/library/Icingadb/Widget/Detail/ObjectDetail.php +++ b/library/Icingadb/Widget/Detail/ObjectDetail.php @@ -21,6 +21,8 @@ use Icinga\Module\Icingadb\Common\Macros; use Icinga\Module\Icingadb\Compat\CompatHost; use Icinga\Module\Icingadb\Model\CustomvarFlat; +use Icinga\Module\Icingadb\Model\DependencyEdge; +use Icinga\Module\Icingadb\Model\DependencyNode; use Icinga\Module\Icingadb\Model\Service; use Icinga\Module\Icingadb\Model\UnreachableParent; use Icinga\Module\Icingadb\Redis\VolatileStateResults; @@ -37,6 +39,8 @@ use Icinga\Module\Icingadb\Util\PluginOutput; use Icinga\Module\Icingadb\Widget\ItemList\DowntimeList; use Icinga\Module\Icingadb\Widget\ShowMore; +use ipl\Sql\Expression; +use ipl\Sql\Filter\Exists; use ipl\Web\Widget\CopyToClipboard; use ipl\Web\Widget\EmptyState; use ipl\Web\Widget\HorizontalKeyValue; @@ -657,4 +661,80 @@ protected function createRootProblems(): ?array ) ]; } + + /** + * Create a list of objects affected by the object that is a part of failed dependency + * + * @return ?BaseHtmlElement[] + */ + protected function createAffectedObjects(): ?array + { + 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' + ]) + ->setResultSetClass(VolatileStateResults::class) + ->limit(5) + ->orderBy([ + 'host.state.severity', + 'host.state.last_state_change', + 'service.state.severity', + 'service.state.last_state_change', + 'redundancy_group.state.failed', + 'redundancy_group.state.last_state_change' + ], SORT_DESC); + + $failedEdges = DependencyEdge::on($this->getDb()) + ->utilize('child') + ->columns([new Expression('1')]) + ->filter(Filter::equal('dependency.state.failed', 'y')); + + if ($this->object instanceof Host) { + $failedEdges + ->filter(Filter::equal('parent.host.id', $this->object->id)) + ->filter(Filter::unlike('parent.service.id', '*')); + } else { + $failedEdges->filter(Filter::equal('parent.service.id', $this->object->id)); + } + + $failedEdges->getFilter()->metaData()->set('forceOptimization', false); + $edgeResolver = $failedEdges->getResolver(); + + $childAlias = $edgeResolver->getAlias( + $edgeResolver->resolveRelation($failedEdges->getModel()->getTableName() . '.child')->getTarget() + ); + + $affectedObjects->filter(new Exists( + $failedEdges->assembleSelect() + ->where( + "$childAlias.id = " + . $affectedObjects->getResolver() + ->qualifyColumn('id', $affectedObjects->getModel()->getTableName()) + ) + )); + + $this->applyRestrictions($affectedObjects); + + return [ + HtmlElement::create('h2', null, Text::create(t('Affected Objects'))), + (new DependencyNodeList($affectedObjects))->setEmptyStateMessage( + t('You are not authorized to view these objects.') + ) + ]; + } } 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(),