diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index 4257066b..933b991f 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -10,6 +10,7 @@ use gipfl\IcingaWeb2\Widget\Tabs; use Exception; use Icinga\Module\Director\CustomVariable\CustomVariableDictionary; use Icinga\Module\Director\Db\AppliedServiceSetLoader; +use Icinga\Module\Director\DirectorObject\Lookup\ServiceFinder; use Icinga\Module\Director\Forms\IcingaAddServiceForm; use Icinga\Module\Director\Forms\IcingaServiceForm; use Icinga\Module\Director\Forms\IcingaServiceSetForm; @@ -24,7 +25,6 @@ use Icinga\Module\Director\Web\Table\IcingaHostAppliedForServiceTable; use Icinga\Module\Director\Web\Table\IcingaHostAppliedServicesTable; use Icinga\Module\Director\Web\Table\IcingaHostServiceTable; use Icinga\Module\Director\Web\Table\IcingaServiceSetServiceTable; -use Icinga\Module\Director\Web\Widget\HostServiceRedirector; class HostController extends ObjectController { @@ -100,15 +100,12 @@ class HostController extends ObjectController )); } - /** - * @throws \Icinga\Exception\NotFoundError - */ public function findserviceAction() { $host = $this->getHostObject(); - $redirector = new HostServiceRedirector($host, $this->getAuth()); $this->redirectNow( - $redirector->getRedirectionUrl($this->params->get('service')) + (new ServiceFinder($host, $this->getAuth())) + ->getRedirectionUrl($this->params->get('service')) ); } diff --git a/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php b/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php new file mode 100644 index 00000000..f25c4079 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php @@ -0,0 +1,87 @@ +hostName = $hostName; + $this->serviceName= $serviceName; + $this->serviceApplyRuleId = $serviceApplyRuleId; + } + + public static function find(IcingaHost $host, $serviceName) + { + $matcher = HostApplyMatches::prepare($host); + $connection = $host->getConnection(); + foreach (static::fetchApplyRulesByServiceName($connection, $serviceName) as $rule) { + if ($matcher->matchesFilter($rule->filter)) { + return new static($host->getObjectName(), $serviceName, (int) $rule->id); + } + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + /** + * @return int + */ + public function getServiceApplyRuleId() + { + return $this->serviceApplyRuleId; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/appliedservice', [ + 'name' => $this->hostName, + 'service_id' => $this->serviceApplyRuleId, + ]); + } + + protected static function fetchApplyRulesByServiceName(Db $connection, $serviceName) + { + $db = $connection->getDbAdapter(); + $query = $db->select() + ->from(['s' => 'icinga_service'], [ + 'id' => 's.id', + 'name' => 's.object_name', + 'assign_filter' => 's.assign_filter', + ]) + ->where('object_name = ?', $serviceName) + ->where('object_type = ? AND assign_filter IS NOT NULL', 'apply'); + + $allRules = $db->fetchAll($query); + foreach ($allRules as $rule) { + $rule->filter = Filter::fromQueryString($rule->assign_filter); + } + + return $allRules; + } +} diff --git a/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php b/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php new file mode 100644 index 00000000..56eb8ab1 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php @@ -0,0 +1,94 @@ +hostName = $hostName; + $this->serviceName = $serviceName; + $this->serviceSetName = $serviceSetName; + } + + public static function find(IcingaHost $host, $serviceName) + { + $matcher = HostApplyMatches::prepare($host); + $connection = $host->getConnection(); + foreach (static::fetchServiceSetApplyRulesByServiceName($connection, $serviceName) as $rule) { + if ($matcher->matchesFilter($rule->filter)) { + return new static($host->getObjectName(), $serviceName, $rule->service_set_name); + } + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + /** + * @return string + */ + public function getServiceSetName() + { + return $this->serviceSetName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/servicesetservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'set' => $this->serviceSetName, + ]); + } + + protected static function fetchServiceSetApplyRulesByServiceName(Db $connection, $serviceName) + { + $db = $connection->getDbAdapter(); + $query = $db->select() + ->from(['s' => 'icinga_service'], [ + 'id' => 's.id', + 'name' => 's.object_name', + 'assign_filter' => 'ss.assign_filter', + 'service_set_name' => 'ss.object_name', + ]) + ->join( + ['ss' => 'icinga_service_set'], + 's.service_set_id = ss.id', + [] + ) + ->where('s.object_name = ?', $serviceName) + ->where('ss.assign_filter IS NOT NULL'); + + $allRules = $db->fetchAll($query); + foreach ($allRules as $rule) { + $rule->filter = Filter::fromQueryString($rule->assign_filter); + } + + return $allRules; + } +} diff --git a/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php b/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php new file mode 100644 index 00000000..6303086f --- /dev/null +++ b/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php @@ -0,0 +1,72 @@ +hostName = $hostName; + $this->hostTemplateName = $hostTemplateName; + $this->serviceName= $serviceName; + } + + public static function find(IcingaHost $host, $serviceName) + { + foreach (IcingaTemplateRepository::instanceByObject($host)->getTemplatesFor($host, true) as $parent) { + if (IcingaService::exists([ + 'host_id' => $parent->get('id'), + 'object_name' => $serviceName + ], $host->getConnection())) { + return new static( + $host->getObjectName(), + $parent->getObjectName(), + $serviceName + ); + } + } + + return false; + } + + public function getHostName() + { + return $this->hostName; + } + + /** + * @return string + */ + public function getHostTemplateName() + { + return $this->hostTemplateName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/inheritedservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'inheritedFrom' => $this->hostTemplateName + ]); + } +} diff --git a/library/Director/DirectorObject/Lookup/ServiceFinder.php b/library/Director/DirectorObject/Lookup/ServiceFinder.php new file mode 100644 index 00000000..fa02a586 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/ServiceFinder.php @@ -0,0 +1,66 @@ +host = $host; + $this->auth = $auth; + $this->db = $host->getConnection(); + } + + /** + * @param $serviceName + * @return Url + */ + public function getRedirectionUrl($serviceName) + { + if ($this->auth->hasPermission('director/host')) { + foreach ([ + SingleServiceInfo::class, + InheritedServiceInfo::class, + ServiceSetServiceInfo::class, + AppliedServiceInfo::class, + AppliedServiceSetServiceInfo::class, + ] as $class) { + /** @var ServiceInfo $class */ + if ($info = $class::find($this->host, $serviceName)) { + return $info->getUrl(); + } + } + } + if ($this->auth->hasPermission('director/monitoring/services-ro')) { + return Url::fromPath('director/host/servicesro', [ + 'name' => $this->host->getObjectName(), + 'service' => $serviceName + ]); + } + + return Url::fromPath('director/host/invalidservice', [ + 'name' => $this->host->getObjectName(), + 'service' => $serviceName, + ]); + } +} diff --git a/library/Director/DirectorObject/Lookup/ServiceInfo.php b/library/Director/DirectorObject/Lookup/ServiceInfo.php new file mode 100644 index 00000000..6379135b --- /dev/null +++ b/library/Director/DirectorObject/Lookup/ServiceInfo.php @@ -0,0 +1,35 @@ +hostName = $hostName; + $this->serviceName = $serviceName; + $this->serviceSetName = $serviceSetName; + } + + public static function find(IcingaHost $host, $serviceName) + { + $ids = [$host->get('id')]; + + foreach (IcingaTemplateRepository::instanceByObject($host)->getTemplatesFor($host, true) as $parent) { + $ids[] = $parent->get('id'); + } + + $db = $host->getConnection()->getDbAdapter(); + $query = $db->select() + ->from( + ['s' => 'icinga_service'], + ['service_set_name' => 'ss.object_name',] + )->join( + ['ss' => 'icinga_service_set'], + 's.service_set_id = ss.id', + [] + )->join( + ['hsi' => 'icinga_service_set_inheritance'], + 'hsi.parent_service_set_id = ss.id', + [] + )->join( + ['hs' => 'icinga_service_set'], + 'hs.id = hsi.service_set_id', + [] + )->where('hs.host_id IN (?)', $ids) + ->where('s.object_name = ?', $serviceName); + + if ($row = $db->fetchRow($query)) { + return new static($host->getObjectName(), $serviceName, $row->service_set_name); + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getName() + { + return $this->serviceName; + } + + /** + * @return string + */ + public function getServiceSetName() + { + return $this->serviceSetName; + } + + public function getUrl() + { + return Url::fromPath('director/host/servicesetservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'set' => $this->serviceSetName, + ]); + } +} diff --git a/library/Director/DirectorObject/Lookup/SingleServiceInfo.php b/library/Director/DirectorObject/Lookup/SingleServiceInfo.php new file mode 100644 index 00000000..931ea33f --- /dev/null +++ b/library/Director/DirectorObject/Lookup/SingleServiceInfo.php @@ -0,0 +1,50 @@ +hostName = $hostName; + $this->serviceName= $serviceName; + } + + public static function find(IcingaHost $host, $serviceName) + { + if (IcingaService::exists([ + 'host_id' => $host->get('id'), + 'object_name' => $serviceName + ], $host->getConnection())) { + return new static($host->getObjectName(), $serviceName); + } + + return false; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/service', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + ]); + } +} diff --git a/library/Director/Web/Widget/HostServiceRedirector.php b/library/Director/Web/Widget/HostServiceRedirector.php deleted file mode 100644 index 16bff78e..00000000 --- a/library/Director/Web/Widget/HostServiceRedirector.php +++ /dev/null @@ -1,264 +0,0 @@ -host = $host; - $this->auth = $auth; - $this->db = $host->getConnection(); - } - - /** - * @param $serviceName - * @return Url - * @throws \Icinga\Exception\NotFoundError - */ - public function getRedirectionUrl($serviceName) - { - if ($this->auth->hasPermission('director/host')) { - if ($url = $this->getSingleServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getParentServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getAppliedServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getServiceSetServiceUrl($serviceName)) { - return $url; - } elseif ($url = $this->getAppliedServiceSetUrl($serviceName)) { - return $url; - } - } elseif ($this->auth->hasPermission('director/monitoring/services-ro')) { - return Url::fromPath('director/host/servicesro', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName - ]); - } - - return Url::fromPath('director/host/invalidservice', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName, - ]); - } - - /** - * @return IcingaHost[] - * @throws \Icinga\Exception\NotFoundError - */ - protected function getParents() - { - if ($this->parents === null) { - $this->parents = IcingaTemplateRepository::instanceByObject( - $this->host - )->getTemplatesFor($this->host, true); - } - - return $this->parents; - } - - /** - * @param $serviceName - * @return Url|null - */ - protected function getSingleServiceUrl($serviceName) - { - if (IcingaService::exists([ - 'host_id' => $this->host->get('id'), - 'object_name' => $serviceName - ], $this->db)) { - return Url::fromPath('director/service/edit', [ - 'name' => $serviceName, - 'host' => $this->host->getObjectName() - ]); - } - - return null; - } - - /** - * @param $serviceName - * @return Url|null - * @throws \Icinga\Exception\NotFoundError - */ - protected function getParentServiceUrl($serviceName) - { - foreach ($this->getParents() as $parent) { - if (IcingaService::exists([ - 'host_id' => $parent->get('id'), - 'object_name' => $serviceName - ], $this->db)) { - return Url::fromPath('director/host/inheritedservice', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName, - 'inheritedFrom' => $parent->getObjectName() - ]); - } - } - - return null; - } - - /** - * @param $serviceName - * @return Url|null - * @throws \Icinga\Exception\NotFoundError - */ - protected function getServiceSetServiceUrl($serviceName) - { - $ids = [$this->host->get('id')]; - - foreach ($this->getParents() as $parent) { - $ids[] = $parent->get('id'); - } - - $db = $this->db->getDbAdapter(); - $query = $db->select() - ->from( - ['s' => 'icinga_service'], - ['service_set_name' => 'ss.object_name',] - )->join( - ['ss' => 'icinga_service_set'], - 's.service_set_id = ss.id', - [] - )->join( - ['hsi' => 'icinga_service_set_inheritance'], - 'hsi.parent_service_set_id = ss.id', - [] - )->join( - ['hs' => 'icinga_service_set'], - 'hs.id = hsi.service_set_id', - [] - )->where('hs.host_id IN (?)', $ids) - ->where('s.object_name = ?', $serviceName); - - if ($row = $db->fetchRow($query)) { - return Url::fromPath('director/host/servicesetservice', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName, - 'set' => $row->service_set_name - ]); - } - - return null; - } - - /** - * @param $serviceName - * @return Url|null - */ - protected function getAppliedServiceUrl($serviceName) - { - $matcher = $this->getHostApplyMatcher(); - foreach ($this->fetchAllApplyRulesForService($serviceName) as $rule) { - if ($matcher->matchesFilter($rule->filter)) { - return Url::fromPath('director/host/appliedservice', [ - 'name' => $this->host->getObjectName(), - 'service_id' => $rule->id, - ]); - } - } - - return null; - } - - /** - * @param $serviceName - * @return Url|null - */ - protected function getAppliedServiceSetUrl($serviceName) - { - $matcher = $this->getHostApplyMatcher(); - foreach ($this->fetchAllServiceSetApplyRulesForService($serviceName) as $rule) { - if ($matcher->matchesFilter($rule->filter)) { - return Url::fromPath('director/host/servicesetservice', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName, - 'set' => $rule->service_set_name - ]); - } - } - - return null; - } - - protected function getHostApplyMatcher() - { - if ($this->applyMatcher === null) { - $this->applyMatcher = HostApplyMatches::prepare($this->host); - } - - return $this->applyMatcher; - } - - protected function fetchAllApplyRulesForService($serviceName) - { - $db = $this->db->getDbAdapter(); - $query = $db->select()->from( - ['s' => 'icinga_service'], - [ - 'id' => 's.id', - 'name' => 's.object_name', - 'assign_filter' => 's.assign_filter', - ] - )->where('object_name = ?', $serviceName) - ->where('object_type = ? AND assign_filter IS NOT NULL', 'apply'); - - $allRules = $db->fetchAll($query); - foreach ($allRules as $rule) { - $rule->filter = Filter::fromQueryString($rule->assign_filter); - } - - return $allRules; - } - - protected function fetchAllServiceSetApplyRulesForService($serviceName) - { - $db = $this->db->getDbAdapter(); - $query = $db->select()->from( - ['s' => 'icinga_service'], - [ - 'id' => 's.id', - 'name' => 's.object_name', - 'assign_filter' => 'ss.assign_filter', - 'service_set_name' => 'ss.object_name', - ] - )->join( - ['ss' => 'icinga_service_set'], - 's.service_set_id = ss.id', - [] - )->where('s.object_name = ?', $serviceName) - ->where('ss.assign_filter IS NOT NULL'); - - $allRules = $db->fetchAll($query); - foreach ($allRules as $rule) { - $rule->filter = Filter::fromQueryString($rule->assign_filter); - } - - return $allRules; - } -}