Icingadb/CustomVarRenderer: Add error handling

This commit is contained in:
raviks789 2024-08-30 12:01:15 +02:00 committed by Johannes Meyer
parent 0e744630d7
commit dbacfa21c0

View File

@ -5,6 +5,7 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError; use Icinga\Exception\NotFoundError;
use Icinga\Module\Director\Daemon\Logger;
use Icinga\Module\Director\Db; use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\AppliedServiceSetLoader; use Icinga\Module\Director\Db\AppliedServiceSetLoader;
use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Director\Objects\IcingaHost;
@ -22,6 +23,7 @@ use ipl\Html\HtmlElement;
use ipl\Html\Text; use ipl\Html\Text;
use ipl\Html\ValidHtml; use ipl\Html\ValidHtml;
use ipl\Orm\Model; use ipl\Orm\Model;
use Throwable;
class CustomVarRenderer extends CustomVarRendererHook class CustomVarRenderer extends CustomVarRendererHook
{ {
@ -61,164 +63,183 @@ class CustomVarRenderer extends CustomVarRendererHook
public function prefetchForObject(Model $object): bool public function prefetchForObject(Model $object): bool
{ {
if ($object instanceof Host) {
$host = $object;
$service = null;
} elseif ($object instanceof Service) {
$host = $object->host;
$service = $object;
} else {
return false;
}
$db = $this->db();
try { try {
$directorHostObj = IcingaHost::load($host->name, $db); if ($object instanceof Host) {
$directorServiceObj = null; $host = $object;
if ($service !== null) { $service = null;
$serviceOrigin = ['direct', 'applied', 'inherited', 'service-set']; } elseif ($object instanceof Service) {
$serviceName = $service->name; $host = $object->host;
$i = 0; $service = $object;
do { } else {
if ($i > 3) { return false;
return false; }
} elseif ($serviceOrigin[$i] === 'direct') {
$directorServiceObj = IcingaService::loadOptional([
'host_id' => $directorHostObj->get('id'),
'object_name' => $serviceName
], $db);
} elseif ($serviceOrigin[$i] === 'inherited') {
$templateResolver = new IcingaTemplateResolver($directorHostObj);
$parentIds = $templateResolver->listParentIds(); $db = $this->db();
$query = $db->getDbAdapter()->select()->from('icinga_service') try {
->where('object_name = ?', $serviceName) $directorHostObj = IcingaHost::load($host->name, $db);
->where('host_id IN (?)', $parentIds); $directorServiceObj = null;
if ($service !== null) {
$serviceOrigin = ['direct', 'applied', 'inherited', 'service-set'];
$serviceName = $service->name;
$i = 0;
do {
if ($i > 3) {
Logger::error("Failed to find service '%s' on host '%s'", $serviceName, $host->name);
$directorServices = IcingaService::loadAll( return false;
$db, } elseif ($serviceOrigin[$i] === 'direct') {
$query, $directorServiceObj = IcingaService::loadOptional([
'object_name' 'host_id' => $directorHostObj->get('id'),
); 'object_name' => $serviceName
], $db);
} elseif ($serviceOrigin[$i] === 'inherited') {
$templateResolver = new IcingaTemplateResolver($directorHostObj);
$directorServiceObj = current($directorServices); $parentIds = $templateResolver->listParentIds();
} elseif ($serviceOrigin[$i] === 'applied') {
$appliedFilterQuery = IcingaHostAppliedServicesTable::load($directorHostObj)->getQuery();
foreach ($appliedFilterQuery->fetchAll() as $appliedService) { $query = $db->getDbAdapter()->select()->from('icinga_service')
if ($appliedService->name === $serviceName) { ->where('object_name = ?', $serviceName)
$query = $db->getDbAdapter()->select()->from('icinga_service') ->where('host_id IN (?)', $parentIds);
->where('object_name = ?', $serviceName)
->where("object_type = 'apply'")
->where('assign_filter = ?', $appliedService->assign_filter);
$directorAppliedServices = IcingaService::loadAll( $directorServices = IcingaService::loadAll(
$db, $db,
$query, $query,
'object_name' 'object_name'
); );
$directorServiceObj = current($directorAppliedServices); $directorServiceObj = current($directorServices);
} elseif ($serviceOrigin[$i] === 'applied') {
$appliedFilterQuery = IcingaHostAppliedServicesTable::load($directorHostObj)->getQuery();
break; foreach ($appliedFilterQuery->fetchAll() as $appliedService) {
if ($appliedService->name === $serviceName) {
$query = $db->getDbAdapter()->select()->from('icinga_service')
->where('object_name = ?', $serviceName)
->where("object_type = 'apply'")
->where('assign_filter = ?', $appliedService->assign_filter);
$directorAppliedServices = IcingaService::loadAll(
$db,
$query,
'object_name'
);
$directorServiceObj = current($directorAppliedServices);
break;
}
} }
} } elseif ($serviceOrigin[$i] === 'service-set') {
} elseif ($serviceOrigin[$i] === 'service-set') { $templateResolver = new IcingaTemplateResolver($directorHostObj);
$templateResolver = new IcingaTemplateResolver($directorHostObj);
$hostServiceSets = $directorHostObj->fetchServiceSets() $hostServiceSets = $directorHostObj->fetchServiceSets()
+ AppliedServiceSetLoader::fetchForHost($directorHostObj); + AppliedServiceSetLoader::fetchForHost($directorHostObj);
$parents = $templateResolver->fetchParents(); $parents = $templateResolver->fetchParents();
foreach ($parents as $parent) { foreach ($parents as $parent) {
$hostServiceSets += $parent->fetchServiceSets(); $hostServiceSets += $parent->fetchServiceSets();
$hostServiceSets += AppliedServiceSetLoader::fetchForHost($parent); $hostServiceSets += AppliedServiceSetLoader::fetchForHost($parent);
} }
foreach ($hostServiceSets as $hostServiceSet) { foreach ($hostServiceSets as $hostServiceSet) {
foreach ($hostServiceSet->getServiceObjects() as $setServiceObject) { foreach ($hostServiceSet->getServiceObjects() as $setServiceObject) {
if ($setServiceObject->getObjectName() === $serviceName) { if ($setServiceObject->getObjectName() === $serviceName) {
$directorServiceObj = $setServiceObject; $directorServiceObj = $setServiceObject;
break 2; break 2;
}
} }
} }
} }
}
$i++; $i++;
} while (! $directorServiceObj); } while (! $directorServiceObj);
}
} catch (NotFoundError $_) {
if ($service !== null) {
Logger::error("Failed to find service '%s' on host '%s'", $service->name, $host->name);
} else {
Logger::error('Failed to find host %s', $host->name);
}
return false;
} }
} catch (NotFoundError $_) {
return false;
}
if ($service === null) { if ($service === null) {
$fields = (new IcingaObjectFieldLoader($directorHostObj))->getFields(); $fields = (new IcingaObjectFieldLoader($directorHostObj))->getFields();
} else {
$fields = (new IcingaObjectFieldLoader($directorServiceObj))->getFields();
}
if (empty($fields)) {
return false;
}
$fieldsWithDataLists = [];
foreach ($fields as $field) {
$this->fieldConfig[$field->get('varname')] = [
'label' => $field->get('caption'),
'group' => $field->getCategoryName(),
'visibility' => $field->getSetting('visibility')
];
if ($field->get('datatype') === 'Icinga\Module\Director\DataType\DataTypeDatalist') {
$fieldsWithDataLists[$field->get('id')] = $field;
} elseif ($field->get('datatype') === 'Icinga\Module\Director\DataType\DataTypeDictionary') {
$this->dictionaryNames[] = $field->get('varname');
}
}
if (! empty($fieldsWithDataLists)) {
if ($this->db()->getDbType() === 'pgsql') {
$joinCondition = 'CAST(dds.setting_value AS INTEGER) = dde.list_id';
} else { } else {
$joinCondition = 'dds.setting_value = dde.list_id'; $fields = (new IcingaObjectFieldLoader($directorServiceObj))->getFields();
} }
$dataListEntries = $db->select()->from( if (empty($fields)) {
['dds' => 'director_datafield_setting'], return false;
[
'dds.datafield_id',
'dde.entry_name',
'dde.entry_value'
]
)->join(
['dde' => 'director_datalist_entry'],
$joinCondition,
[]
)->where('dds.datafield_id', array_keys($fieldsWithDataLists))
->where('dds.setting_name', 'datalist_id');
foreach ($dataListEntries as $dataListEntry) {
$field = $fieldsWithDataLists[$dataListEntry->datafield_id];
$this->datalistMaps[$field->get('varname')][$dataListEntry->entry_name] = $dataListEntry->entry_value;
} }
$fieldsWithDataLists = [];
foreach ($fields as $field) {
$this->fieldConfig[$field->get('varname')] = [
'label' => $field->get('caption'),
'group' => $field->getCategoryName(),
'visibility' => $field->getSetting('visibility')
];
if ($field->get('datatype') === 'Icinga\Module\Director\DataType\DataTypeDatalist') {
$fieldsWithDataLists[$field->get('id')] = $field;
} elseif ($field->get('datatype') === 'Icinga\Module\Director\DataType\DataTypeDictionary') {
$this->dictionaryNames[] = $field->get('varname');
}
}
if (! empty($fieldsWithDataLists)) {
if ($this->db()->getDbType() === 'pgsql') {
$joinCondition = 'CAST(dds.setting_value AS INTEGER) = dde.list_id';
} else {
$joinCondition = 'dds.setting_value = dde.list_id';
}
$dataListEntries = $db->select()->from(
['dds' => 'director_datafield_setting'],
[
'dds.datafield_id',
'dde.entry_name',
'dde.entry_value'
]
)->join(
['dde' => 'director_datalist_entry'],
$joinCondition,
[]
)->where('dds.datafield_id', array_keys($fieldsWithDataLists))
->where('dds.setting_name', 'datalist_id');
foreach ($dataListEntries as $dataListEntry) {
$field = $fieldsWithDataLists[$dataListEntry->datafield_id];
$this->datalistMaps[$field->get('varname')][$dataListEntry->entry_name]
= $dataListEntry->entry_value;
}
}
return true;
} catch (Throwable $e) {
Logger::error("%s\n%s", $e, $e->getTraceAsString());
return false;
} }
return true;
} }
public function renderCustomVarKey(string $key) public function renderCustomVarKey(string $key)
{ {
if (isset($this->fieldConfig[$key]['label'])) { try {
return new HtmlElement( if (isset($this->fieldConfig[$key]['label'])) {
'span', return new HtmlElement(
Attributes::create(['title' => $this->fieldConfig[$key]['label'] . " [$key]"]), 'span',
Text::create($this->fieldConfig[$key]['label']) Attributes::create(['title' => $this->fieldConfig[$key]['label'] . " [$key]"]),
); Text::create($this->fieldConfig[$key]['label'])
);
}
} catch (Throwable $e) {
Logger::error("%s\n%s", $e, $e->getTraceAsString());
} }
return null; return null;
@ -226,20 +247,24 @@ class CustomVarRenderer extends CustomVarRendererHook
public function renderCustomVarValue(string $key, $value) public function renderCustomVarValue(string $key, $value)
{ {
if (isset($this->fieldConfig[$key])) { try {
if ($this->fieldConfig[$key]['visibility'] === 'hidden') { if (isset($this->fieldConfig[$key])) {
return '***'; if ($this->fieldConfig[$key]['visibility'] === 'hidden') {
} return '***';
}
if (isset($this->datalistMaps[$key][$value])) { if (isset($this->datalistMaps[$key][$value])) {
return new HtmlElement( return new HtmlElement(
'span', 'span',
Attributes::create(['title' => $this->datalistMaps[$key][$value] . " [$value]"]), Attributes::create(['title' => $this->datalistMaps[$key][$value] . " [$value]"]),
Text::create($this->datalistMaps[$key][$value]) Text::create($this->datalistMaps[$key][$value])
); );
} elseif ($value !== null && in_array($key, $this->dictionaryNames)) { } elseif ($value !== null && in_array($key, $this->dictionaryNames)) {
return $this->renderDictionaryVal($key, (array) $value); return $this->renderDictionaryVal($key, (array) $value);
}
} }
} catch (Throwable $e) {
Logger::error("%s\n%s", $e, $e->getTraceAsString());
} }
return null; return null;