Imported Node: Don't break view if source config file is faulty (#394)

refs #370
This commit is contained in:
Johannes Meyer 2023-08-09 16:05:52 +02:00 committed by GitHub
commit ff0cb21a2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 75 additions and 26 deletions

View file

@ -52,7 +52,7 @@ class CleanupCommand extends Command
$bp = $this->storage->loadProcess($configName);
} catch (Exception $e) {
Logger::error(
'Failed to scan the %s.conf file for missing nodes. Invalid config found.',
'Failed to scan the %s.conf file for missing nodes. Faulty config found.',
$configName
);

View file

@ -448,7 +448,7 @@ class ProcessController extends Controller
protected function prepareMissingNodeLinks(HtmlElement $ul): void
{
$missing = $this->bp->getMissingChildren();
$missing = array_keys($this->bp->getMissingChildren());
if (! empty($missing)) {
$missingLinkedNodes = null;
foreach ($this->bp->getImportedNodes() as $process) {

View file

@ -130,6 +130,9 @@ class BpConfig
/** @var ProcessChanges */
protected $appliedChanges;
/** @var bool Whether the config is faulty */
protected $isFaulty = false;
public function __construct()
{
}
@ -577,7 +580,13 @@ class BpConfig
public function getImportedConfig($name)
{
if (! isset($this->importedConfigs[$name])) {
$import = $this->storage()->loadProcess($name);
try {
$import = $this->storage()->loadProcess($name);
} catch (Exception $e) {
$import = (new static())
->setName($name)
->setFaulty();
}
if ($this->usesSoftStates()) {
$import->useSoftStates();
@ -687,9 +696,17 @@ class BpConfig
{
if ($this->hasBpNode($name)) {
return $this->nodes[$name];
} else {
throw new NotFoundError('Trying to access a missing business process node "%s"', $name);
}
$msg = $this->isFaulty()
? sprintf(
t('Trying to import node "%s" from faulty config file "%s.conf"'),
self::unescapeName($name),
$this->getName()
)
: sprintf(t('Trying to access a missing business process node "%s"'), $name);
throw new NotFoundError($msg);
}
/**
@ -912,7 +929,10 @@ class BpConfig
throw new IcingaException($msg);
}
$this->errors[] = $msg;
if (! in_array($msg, $this->errors)) {
$this->errors[] = $msg;
}
return $this;
}
@ -1070,4 +1090,28 @@ class BpConfig
return array_pad($parts, 2, null);
}
/**
* Set whether the config is faulty
*
* @param bool $isFaulty
*
* @return $this
*/
public function setFaulty(bool $isFaulty = true): self
{
$this->isFaulty = $isFaulty;
return $this;
}
/**
* Get whether the config is faulty
*
* @return bool
*/
public function isFaulty(): bool
{
return $this->isFaulty;
}
}

View file

@ -275,11 +275,11 @@ class BpNode extends Node
foreach ($this->getChildren() as $child) {
if ($child->isMissing()) {
$missing[$child->getName()] = $child;
$missing[$child->getAlias()] = $child;
}
foreach ($child->getMissingChildren() as $m) {
$missing[$m->getName()] = $m;
$missing[$m->getAlias()] = $m;
}
}

View file

@ -90,6 +90,15 @@ class ImportedNode extends BpNode
return $this->childNames;
}
public function isMissing()
{
if ($this->missing === null && $this->getBpConfig()->isFaulty()) {
$this->missing = true;
}
return parent::isMissing();
}
/**
* @return BpNode
*/
@ -121,10 +130,9 @@ class ImportedNode extends BpNode
));
$node->setBpConfig($this->getBpConfig());
$node->setState(2);
$node->setMissing(false)
$node->setMissing()
->setDowntime(false)
->setAck(false)
->setAlias($e->getMessage());
->setAck(false);
return $node;
}

View file

@ -12,6 +12,7 @@ use Icinga\Web\Url;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Web\Widget\Icon;
use ipl\Web\Widget\Link;
use ipl\Web\Widget\StateBall;
class NodeTile extends BaseHtmlElement
@ -102,11 +103,7 @@ class NodeTile extends BaseHtmlElement
$this->add($link);
} else {
$this->add(Html::tag(
'span',
['class' => 'missing-node-msg'],
sprintf('Trying to access a missing business process node "%s"', $node->getNodeName())
));
$this->add(new Link($node->getAlias(), $this->getMainNodeUrl($node)->getAbsoluteUrl()));
}
if ($this->renderer->rendersSubNode()
@ -210,12 +207,15 @@ class NodeTile extends BaseHtmlElement
new Icon('sitemap')
));
if ($node instanceof ImportedNode) {
if ($node->getBpConfig()->hasNode($node->getName())) {
$bpConfig = $node->getBpConfig();
if ($bpConfig->isFaulty() || $bpConfig->hasNode($node->getName())) {
$this->actions()->add(Html::tag(
'a',
[
'data-base-target' => '_next',
'href' => $this->renderer->getSourceUrl($node)->getAbsoluteUrl(),
'href' => $bpConfig->isFaulty()
? $this->renderer->getBaseUrl()->setParam('config', $bpConfig->getName())
: $this->renderer->getSourceUrl($node)->getAbsoluteUrl(),
'title' => mt(
'businessprocess',
'Show this process as part of its original configuration'

View file

@ -234,7 +234,9 @@ class TreeRenderer extends Renderer
} elseif ($differentConfig) {
$summary->add($this->actionIcon(
'share',
$this->getSourceUrl($node)->addParams(['mode' => 'tree'])->getAbsoluteUrl(),
$node->getBpConfig()->isFaulty()
? $this->getBaseUrl()->setParam('config', $node->getBpConfig()->getName())
: $this->getSourceUrl($node)->addParams(['mode' => 'tree'])->getAbsoluteUrl(),
mt('businessprocess', 'Show this process as part of its original configuration')
)->addAttributes(['data-base-target' => '_next']));
}

View file

@ -100,7 +100,7 @@ class Dashboard extends BaseHtmlElement
$this->add(new BpDashboardTile(
new BpConfig(),
$title,
sprintf(t('File %s has invalid config'), $name . '.conf'),
sprintf(t('File %s has faulty config'), $name . '.conf'),
'file-circle-xmark',
'businessprocess/process/show',
['config' => $name]

View file

@ -481,8 +481,7 @@ td > a > .state-badges {
border: 1px solid @body-bg-color;
}
> a,
.missing-node-msg {
> a {
display: block;
text-decoration: none;
font-size: 0.7em;
@ -492,10 +491,6 @@ td > a > .state-badges {
word-wrap: break-word;
}
.missing-node-msg {
font-size: 0.5em;
}
&:hover {
box-shadow: 0 0 .2em @gray;
}