From ec8a5628dc38946f7707849c9ba8891324f506fa Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 09:55:56 +0200 Subject: [PATCH 1/6] hostgroup/index: Pass a result set to the host list --- application/controllers/HostgroupController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/HostgroupController.php b/application/controllers/HostgroupController.php index 56712b2a..978489db 100644 --- a/application/controllers/HostgroupController.php +++ b/application/controllers/HostgroupController.php @@ -59,7 +59,7 @@ class HostgroupController extends Controller $paginationControl = $this->createPaginationControl($hosts); $viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl); - $hostList = (new HostList($hosts)) + $hostList = (new HostList($hosts->execute())) ->setViewMode($viewModeSwitcher->getViewMode()); yield $this->export($hosts); From 735e3d4a550d462aec140a72a4791f1abf20de52 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 09:56:20 +0200 Subject: [PATCH 2/6] servicegroup/index: Pass a result set to the service list --- application/controllers/ServicegroupController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/ServicegroupController.php b/application/controllers/ServicegroupController.php index 42c22e6e..89fb8296 100644 --- a/application/controllers/ServicegroupController.php +++ b/application/controllers/ServicegroupController.php @@ -65,7 +65,7 @@ class ServicegroupController extends Controller $paginationControl = $this->createPaginationControl($services); $viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl); - $serviceList = (new ServiceList($services)) + $serviceList = (new ServiceList($services->execute())) ->setViewMode($viewModeSwitcher->getViewMode()); yield $this->export($services); From bf0d11ff37f091b5fc215e5a1bcf1dbd7439e730 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 09:56:58 +0200 Subject: [PATCH 3/6] VolatileStateResults: Don't fail completely if redis is unavailable --- .../Icingadb/Redis/VolatileStateResults.php | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php index dd3695e9..abcf1f14 100644 --- a/library/Icingadb/Redis/VolatileStateResults.php +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Redis; +use Exception; use Generator; use Icinga\Application\Benchmark; use Icinga\Module\Icingadb\Common\IcingaRedis; @@ -12,6 +13,7 @@ use Icinga\Module\Icingadb\Model\Service; use ipl\Orm\Query; use ipl\Orm\Resolver; use ipl\Orm\ResultSet; +use Predis\Client; use RuntimeException; class VolatileStateResults extends ResultSet @@ -19,6 +21,9 @@ class VolatileStateResults extends ResultSet /** @var Resolver */ private $resolver; + /** @var Client */ + private $redis; + /** @var bool Whether Redis updates were applied */ private $updatesApplied = false; @@ -27,12 +32,28 @@ class VolatileStateResults extends ResultSet $self = parent::fromQuery($query); $self->resolver = $query->getResolver(); + try { + $self->redis = IcingaRedis::instance()->getConnection(); + } catch (Exception $e) { + // The error has already been logged + } + return $self; } + /** + * Get whether Redis is unavailable + * + * @return bool + */ + public function isRedisUnavailable(): bool + { + return $this->redis === null; + } + public function current() { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->rewind(); } @@ -41,7 +62,7 @@ class VolatileStateResults extends ResultSet public function key(): int { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->rewind(); } @@ -50,7 +71,7 @@ class VolatileStateResults extends ResultSet public function rewind(): void { - if (! $this->updatesApplied && ! $this->isCacheDisabled) { + if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) { $this->updatesApplied = true; $this->advance(); @@ -126,7 +147,7 @@ class VolatileStateResults extends ResultSet protected function fetchStates(string $key, array $ids, array $keys): Generator { - $results = IcingaRedis::instance()->getConnection()->hmget($key, $ids); + $results = $this->redis->hmget($key, $ids); foreach ($results as $i => $json) { if ($json !== null) { $data = json_decode($json, true); From cf23a8fc7c9096b084746424751f1cac3b225347 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 09:58:01 +0200 Subject: [PATCH 4/6] Introduce new widget `Notice` --- library/Icingadb/Widget/Notice.php | 31 ++++++++++++++++++++++++++++++ public/css/widget/notice.less | 23 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 library/Icingadb/Widget/Notice.php create mode 100644 public/css/widget/notice.less diff --git a/library/Icingadb/Widget/Notice.php b/library/Icingadb/Widget/Notice.php new file mode 100644 index 00000000..998ad30d --- /dev/null +++ b/library/Icingadb/Widget/Notice.php @@ -0,0 +1,31 @@ + 'notice']; + + public function __construct($content) + { + $this->content = $content; + } + + protected function assemble() + { + $this->addHtml(new Icon('triangle-exclamation')); + $this->addHtml((new HtmlElement('span'))->add($this->content)); + $this->addHtml(new Icon('triangle-exclamation')); + } +} diff --git a/public/css/widget/notice.less b/public/css/widget/notice.less new file mode 100644 index 00000000..70676656 --- /dev/null +++ b/public/css/widget/notice.less @@ -0,0 +1,23 @@ +// Style + +.notice { + @margin: 1em / 1.25; + @padding: .75em / 1.25; + + .rounded-corners(); + padding: @padding; + color: @text-color-on-icinga-blue; + background-color: @state-warning; + font-weight: bold; + font-size: 1.25em; + + // Layout + display: flex; + align-items: baseline; + justify-content: space-between; + margin: 0 @margin @margin @margin; + + > span { + .text-ellipsis(); + } +} From dd3b77d1a98f43b4d246fbeb5cd945749656d51a Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 09:58:22 +0200 Subject: [PATCH 5/6] StateList: Prepend a notice if redis is unavailable --- library/Icingadb/Widget/ItemList/StateList.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/Icingadb/Widget/ItemList/StateList.php b/library/Icingadb/Widget/ItemList/StateList.php index 471fb4fd..cf6ec0b8 100644 --- a/library/Icingadb/Widget/ItemList/StateList.php +++ b/library/Icingadb/Widget/ItemList/StateList.php @@ -7,6 +7,9 @@ namespace Icinga\Module\Icingadb\Widget\ItemList; use Icinga\Module\Icingadb\Common\BaseItemList; use Icinga\Module\Icingadb\Common\NoSubjectLink; use Icinga\Module\Icingadb\Common\ViewMode; +use Icinga\Module\Icingadb\Redis\VolatileStateResults; +use Icinga\Module\Icingadb\Widget\Notice; +use ipl\Html\HtmlDocument; abstract class StateList extends BaseItemList { @@ -18,5 +21,11 @@ abstract class StateList extends BaseItemList $this->addAttributes(['class' => $this->getViewMode()]); parent::assemble(); + + if ($this->data instanceof VolatileStateResults && $this->data->isRedisUnavailable()) { + $this->prependWrapper((new HtmlDocument())->addHtml(new Notice( + t('Icinga Redis is currently unavailable. The shown information might be outdated.') + ))); + } } } From a86d5635f54627860da8caa1c550badab83e82b2 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 28 Jun 2022 10:10:58 +0200 Subject: [PATCH 6/6] css: Hide notices in controls --- public/css/common.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/css/common.less b/public/css/common.less index b89a161b..7d0bb06b 100644 --- a/public/css/common.less +++ b/public/css/common.less @@ -185,6 +185,10 @@ div.show-more { .show-more { margin-top: .25em; } + + .notice { + display: none; + } } .content > h2:first-child,