diff --git a/application/controllers/NodeController.php b/application/controllers/NodeController.php index 8addc07..e5c657f 100644 --- a/application/controllers/NodeController.php +++ b/application/controllers/NodeController.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Businessprocess\Controllers; +use Exception; use Icinga\Application\Modules\Module; use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport; use Icinga\Module\Businessprocess\Renderer\Breadcrumb; @@ -11,6 +12,8 @@ use Icinga\Module\Businessprocess\State\IcingaDbState; use Icinga\Module\Businessprocess\State\MonitoringState; use Icinga\Module\Businessprocess\Web\Controller; use Icinga\Module\Businessprocess\Web\Url; +use ipl\Html\Html; +use ipl\Web\Widget\Link; class NodeController extends Controller { @@ -24,9 +27,16 @@ class NodeController extends Controller $name = $this->params->get('name'); $this->addTitle($this->translate('Business Impact (%s)'), $name); + $brokenFiles = []; $simulation = Simulation::fromSession($this->session()); foreach ($this->storage()->listProcessNames() as $configName) { - $config = $this->storage()->loadProcess($configName); + try { + $config = $this->storage()->loadProcess($configName); + } catch (Exception $e) { + $meta = $this->storage()->loadMetadata($configName); + $brokenFiles[$meta->get('Title')] = $configName; + continue; + } $parents = []; if ($config->hasNode($name)) { @@ -108,5 +118,31 @@ class NodeController extends Controller if ($content->isEmpty()) { $content->add($this->translate('No impact detected. Is this node part of a business process?')); } + + if (! empty($brokenFiles)) { + $elem = Html::tag( + 'ul', + ['class' => 'broken-files'], + tp( + 'The following business process has an invalid config file and therefore cannot be read:', + 'The following business processes have invalid config files and therefore cannot be read:', + count($brokenFiles) + ) + ); + + foreach ($brokenFiles as $bpName => $fileName) { + $elem->addHtml( + Html::tag( + 'li', + new Link( + sprintf('%s (%s.conf)', $bpName, $fileName), + \ipl\Web\Url::fromPath('businessprocess/process/show', ['config' => $fileName]) + ) + ) + ); + } + + $content->addHtml($elem); + } } } diff --git a/application/forms/AddNodeForm.php b/application/forms/AddNodeForm.php index 5ef11c7..448250c 100644 --- a/application/forms/AddNodeForm.php +++ b/application/forms/AddNodeForm.php @@ -2,6 +2,7 @@ namespace Icinga\Module\Businessprocess\Forms; +use Exception; use Icinga\Module\Businessprocess\BpNode; use Icinga\Module\Businessprocess\BpConfig; use Icinga\Module\Businessprocess\Common\EnumList; @@ -471,7 +472,13 @@ class AddNodeForm extends QuickForm $bp = $this->bp; if ($differentFile) { - $bp = $this->storage->loadProcess($file); + try { + $bp = $this->storage->loadProcess($file); + } catch (Exception $e) { + $this->addError('Cannot add invalid config file'); + + return $list; + } } foreach ($bp->getNodes() as $node) { diff --git a/library/Businessprocess/Web/Component/BpDashboardTile.php b/library/Businessprocess/Web/Component/BpDashboardTile.php index 17d3a0c..9a4a0f6 100644 --- a/library/Businessprocess/Web/Component/BpDashboardTile.php +++ b/library/Businessprocess/Web/Component/BpDashboardTile.php @@ -3,10 +3,12 @@ namespace Icinga\Module\Businessprocess\Web\Component; use Icinga\Module\Businessprocess\BpConfig; -use Icinga\Web\Url; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; use ipl\Html\Text; +use ipl\Web\Url; +use ipl\Web\Widget\Icon; +use ipl\Web\Widget\Link; class BpDashboardTile extends BaseHtmlElement { @@ -16,14 +18,10 @@ class BpDashboardTile extends BaseHtmlElement public function __construct(BpConfig $bp, $title, $description, $icon, $url, $urlParams = null, $attributes = null) { - if (! isset($attributes['href'])) { - $attributes['href'] = Url::fromPath($url, $urlParams ?: []); - } - $this->add(Html::tag( 'div', ['class' => 'bp-link', 'data-base-target' => '_main'], - Html::tag('a', $attributes, Html::tag('i', ['class' => 'icon icon-' . $icon])) + (new Link(new Icon($icon), Url::fromPath($url, $urlParams ?: []), $attributes)) ->add(Html::tag('span', ['class' => 'header'], $title)) ->add($description) )); diff --git a/library/Businessprocess/Web/Component/Dashboard.php b/library/Businessprocess/Web/Component/Dashboard.php index 3423b2f..e78c46c 100644 --- a/library/Businessprocess/Web/Component/Dashboard.php +++ b/library/Businessprocess/Web/Component/Dashboard.php @@ -2,8 +2,10 @@ namespace Icinga\Module\Businessprocess\Web\Component; +use Exception; use Icinga\Application\Modules\Module; use Icinga\Authentication\Auth; +use Icinga\Module\Businessprocess\BpConfig; use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport; use Icinga\Module\Businessprocess\State\IcingaDbState; use Icinga\Module\Businessprocess\State\MonitoringState; @@ -92,7 +94,20 @@ class Dashboard extends BaseHtmlElement $title = $name; } - $bp = $storage->loadProcess($name); + try { + $bp = $storage->loadProcess($name); + } catch (Exception $e) { + $this->add(new BpDashboardTile( + new BpConfig(), + $title, + sprintf(t('File %s has invalid config'), $name . '.conf'), + 'file-circle-xmark', + 'businessprocess/process/show', + ['config' => $name] + )); + + continue; + } if (Module::exists('icingadb') && (! $bp->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend()) diff --git a/library/Businessprocess/Web/Component/DashboardAction.php b/library/Businessprocess/Web/Component/DashboardAction.php index 5ed1845..9bd3240 100644 --- a/library/Businessprocess/Web/Component/DashboardAction.php +++ b/library/Businessprocess/Web/Component/DashboardAction.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Businessprocess\Web\Component; use Icinga\Web\Url; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; +use ipl\Web\Widget\Icon; class DashboardAction extends BaseHtmlElement { @@ -19,7 +20,7 @@ class DashboardAction extends BaseHtmlElement } $this->add(Html::tag('a', $attributes) - ->add(Html::tag('i', ['class' => 'icon icon-' . $icon])) + ->add(new Icon($icon)) ->add(Html::tag('span', ['class' => 'header'], $title)) ->add($description)); } diff --git a/public/css/module.less b/public/css/module.less index 1c2f57e..2d278d3 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -288,6 +288,22 @@ ul.bp { } } +// ** Node inspect broken files **/ +ul.broken-files { + .rounded-corners(); + padding: 1em; + margin: 1em 0; + border: 2px solid @state-warning; + font-size: 1.25em; + list-style: none; + + li { + padding-left: 1em; + font-weight: bold; + } +} +// ** END Node inspect broken files **/ + /** BEGIN Dashboard **/ .overview-dashboard { .header {