From a81473995b9c0a1fc26aeb5d2bee9922a13b2d1a Mon Sep 17 00:00:00 2001 From: raviks789 Date: Fri, 30 Aug 2024 12:01:15 +0200 Subject: [PATCH] Icingadb/CustomVarRenderer: Add error handling --- .../Icingadb/CustomVarRenderer.php | 315 ++++++++++-------- 1 file changed, 170 insertions(+), 145 deletions(-) diff --git a/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php b/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php index 43550d761..fb307a52d 100644 --- a/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php +++ b/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php @@ -5,6 +5,7 @@ use Icinga\Application\Config; use Icinga\Exception\ConfigurationError; use Icinga\Exception\NotFoundError; +use Icinga\Module\Director\Daemon\Logger; use Icinga\Module\Director\Db; use Icinga\Module\Director\Db\AppliedServiceSetLoader; use Icinga\Module\Director\Objects\IcingaHost; @@ -22,6 +23,7 @@ use ipl\Html\Text; use ipl\Html\ValidHtml; use ipl\Orm\Model; +use Throwable; class CustomVarRenderer extends CustomVarRendererHook { @@ -61,164 +63,183 @@ protected function db(): Db 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; - } + try { + if ($object instanceof Host) { + $host = $object; + $service = null; + } elseif ($object instanceof Service) { + $host = $object->host; + $service = $object; + } else { + return false; + } - $db = $this->db(); + $db = $this->db(); + + try { + $directorHostObj = IcingaHost::load($host->name, $db); + $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); + + 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(); + + $query = $db->getDbAdapter()->select()->from('icinga_service') + ->where('object_name = ?', $serviceName) + ->where('host_id IN (?)', $parentIds); + + $directorServices = IcingaService::loadAll( + $db, + $query, + 'object_name' + ); - try { - $directorHostObj = IcingaHost::load($host->name, $db); - $directorServiceObj = null; - if ($service !== null) { - $serviceOrigin = ['direct', 'applied', 'inherited', 'service-set']; - $serviceName = $service->name; - $i = 0; - do { - if ($i > 3) { - 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(); - - $query = $db->getDbAdapter()->select()->from('icinga_service') - ->where('object_name = ?', $serviceName) - ->where('host_id IN (?)', $parentIds); - - $directorServices = IcingaService::loadAll( - $db, - $query, - 'object_name' - ); - - $directorServiceObj = current($directorServices); - } elseif ($serviceOrigin[$i] === 'applied') { - $appliedFilterQuery = IcingaHostAppliedServicesTable::load($directorHostObj)->getQuery(); - - 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; + $directorServiceObj = current($directorServices); + } elseif ($serviceOrigin[$i] === 'applied') { + $appliedFilterQuery = IcingaHostAppliedServicesTable::load($directorHostObj)->getQuery(); + + 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') { - $templateResolver = new IcingaTemplateResolver($directorHostObj); + } elseif ($serviceOrigin[$i] === 'service-set') { + $templateResolver = new IcingaTemplateResolver($directorHostObj); - $hostServiceSets = $directorHostObj->fetchServiceSets() - + AppliedServiceSetLoader::fetchForHost($directorHostObj); + $hostServiceSets = $directorHostObj->fetchServiceSets() + + AppliedServiceSetLoader::fetchForHost($directorHostObj); - $parents = $templateResolver->fetchParents(); + $parents = $templateResolver->fetchParents(); - foreach ($parents as $parent) { - $hostServiceSets += $parent->fetchServiceSets(); - $hostServiceSets += AppliedServiceSetLoader::fetchForHost($parent); - } + foreach ($parents as $parent) { + $hostServiceSets += $parent->fetchServiceSets(); + $hostServiceSets += AppliedServiceSetLoader::fetchForHost($parent); + } - foreach ($hostServiceSets as $hostServiceSet) { - foreach ($hostServiceSet->getServiceObjects() as $setServiceObject) { - if ($setServiceObject->getObjectName() === $serviceName) { - $directorServiceObj = $setServiceObject; + foreach ($hostServiceSets as $hostServiceSet) { + foreach ($hostServiceSet->getServiceObjects() as $setServiceObject) { + if ($setServiceObject->getObjectName() === $serviceName) { + $directorServiceObj = $setServiceObject; - break 2; + break 2; + } } } } - } - $i++; - } while (! $directorServiceObj); - } - } catch (NotFoundError $_) { - return false; - } + $i++; + } 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); + } - if ($service === null) { - $fields = (new IcingaObjectFieldLoader($directorHostObj))->getFields(); - } else { - $fields = (new IcingaObjectFieldLoader($directorServiceObj))->getFields(); - } + return false; + } - if (empty($fields)) { - return false; - } + if ($service === null) { + $fields = (new IcingaObjectFieldLoader($directorHostObj))->getFields(); + } else { + $fields = (new IcingaObjectFieldLoader($directorServiceObj))->getFields(); + } - $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($fields)) { + return false; } - } - 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'; + $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'); + } } - $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; + 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; + return true; + } catch (Throwable $e) { + Logger::error("%s\n%s", $e, $e->getTraceAsString()); + + return false; + } } public function renderCustomVarKey(string $key) { - if (isset($this->fieldConfig[$key]['label'])) { - return new HtmlElement( - 'span', - Attributes::create(['title' => $this->fieldConfig[$key]['label'] . " [$key]"]), - Text::create($this->fieldConfig[$key]['label']) - ); + try { + if (isset($this->fieldConfig[$key]['label'])) { + return new HtmlElement( + 'span', + 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; @@ -226,20 +247,24 @@ public function renderCustomVarKey(string $key) public function renderCustomVarValue(string $key, $value) { - if (isset($this->fieldConfig[$key])) { - if ($this->fieldConfig[$key]['visibility'] === 'hidden') { - return '***'; - } + try { + if (isset($this->fieldConfig[$key])) { + if ($this->fieldConfig[$key]['visibility'] === 'hidden') { + return '***'; + } - if (isset($this->datalistMaps[$key][$value])) { - return new HtmlElement( - 'span', - Attributes::create(['title' => $this->datalistMaps[$key][$value] . " [$value]"]), - Text::create($this->datalistMaps[$key][$value]) - ); - } elseif ($value !== null && in_array($key, $this->dictionaryNames)) { - return $this->renderDictionaryVal($key, (array) $value); + if (isset($this->datalistMaps[$key][$value])) { + return new HtmlElement( + 'span', + Attributes::create(['title' => $this->datalistMaps[$key][$value] . " [$value]"]), + Text::create($this->datalistMaps[$key][$value]) + ); + } elseif ($value !== null && in_array($key, $this->dictionaryNames)) { + return $this->renderDictionaryVal($key, (array) $value); + } } + } catch (Throwable $e) { + Logger::error("%s\n%s", $e, $e->getTraceAsString()); } return null;