IcingaServiceForm: add blacklist/delete button...

...and a lot of related boilerplate to get the "blacklist" feature working
This commit is contained in:
Thomas Gelf 2018-05-25 17:03:33 +02:00
parent ba5e595fd0
commit 8073128d0e
7 changed files with 271 additions and 9 deletions

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Director\Forms;
use Icinga\Data\Filter\Filter;
use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Director\Data\PropertiesFilter\ArrayCustomVariablesFilter;
use Icinga\Module\Director\Exception\NestingError;
@ -43,6 +44,11 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @throws IcingaException
* @throws ProgrammingError
* @throws \Zend_Form_Exception
*/
public function setup()
{
if ($this->providesOverrides()) {
@ -79,6 +85,27 @@ class IcingaServiceForm extends DirectorObjectForm
|| ($this->object && $this->object->usesVarOverrides());
}
/**
* @throws IcingaException
* @throws ProgrammingError
* @throws \Zend_Form_Exception
*/
protected function addFields()
{
if ($this->providesOverrides() && $this->hasBeenBlacklisted()) {
$this->onAddedFields();
return;
} else {
parent::addFields();
}
}
/**
* @throws IcingaException
* @throws ProgrammingError
* @throws \Zend_Form_Exception
*/
protected function onAddedFields()
{
if (! $this->providesOverrides()) {
@ -106,8 +133,140 @@ class IcingaServiceForm extends DirectorObjectForm
$this->setSubmitLabel(false);
}
if ($this->hasBeenBlacklisted()) {
$this->addDeleteButton($this->translate('Restore'));
} else {
$this->addDeleteButton($this->translate('Blacklist'));
}
if (! $this->hasSubmitButton()) {
$this->addDisplayGroup([$this->deleteButtonName], 'buttons', [
'decorators' => [
'FormElements',
['HtmlTag', ['tag' => 'dl']],
'DtDdWrapper',
],
'order' => 1000,
]);
}
}
/**
* @param IcingaService $service
* @return IcingaService
* @throws ProgrammingError
*/
protected function getFirstParent(IcingaService $service)
{
$objects = $service->imports()->getObjects();
if (empty($objects)) {
throw new ProgrammingError('Something went wrong, got no parent');
}
reset($objects);
return current($objects);
}
/**
* @return bool
* @throws IcingaException
* @throws ProgrammingError
*/
protected function hasBeenBlacklisted()
{
if (! $this->providesOverrides() || $this->object === null) {
return false;
}
$host = $this->host;
$service = $this->getFirstParent($this->object);
$db = $this->db->getDbAdapter();
if ($this->providesOverrides()) {
return 1 === (int) $db->fetchOne(
$db->select()->from('icinga_host_service_blacklist', 'COUNT(*)')
->where('host_id = ?', $host->get('id'))
->where('service_id = ?', $service->get('id'))
);
} else {
return false;
}
}
/**
* @param $object
* @throws IcingaException
* @throws ProgrammingError
* @throws \Zend_Db_Adapter_Exception
*/
protected function deleteObject($object)
{
/** @var IcingaService $object */
if ($this->providesOverrides()) {
if ($this->hasBeenBlacklisted()) {
$this->removeFromBlacklist();
} else {
$this->blacklist();
}
} else {
parent::deleteObject($object);
}
}
/**
* @throws IcingaException
* @throws ProgrammingError
* @throws \Zend_Db_Adapter_Exception
*/
protected function blacklist()
{
$host = $this->host;
$service = $this->getFirstParent($this->object);
$db = $this->db->getDbAdapter();
$host->unsetOverriddenServiceVars($service)->store();
if ($db->insert('icinga_host_service_blacklist', [
'host_id' => $host->get('id'),
'service_id' => $service->get('id')
])) {
$msg = sprintf(
$this->translate('%s has been blacklisted on %s'),
$service->getObjectName(),
$host->getObjectName()
);
$this->redirectOnSuccess($msg);
}
}
/**
* @throws IcingaException
* @throws ProgrammingError
*/
protected function removeFromBlacklist()
{
$host = $this->host;
$service = $this->getFirstParent($this->object);
$db = $this->db->getDbAdapter();
$where = implode(' AND ', [
$db->quoteInto('host_id = ?', $host->get('id')),
$db->quoteInto('service_id = ?', $service->get('id')),
]);
if ($db->delete('icinga_host_service_blacklist', $where)) {
$msg = sprintf(
$this->translate('%s has been removed from blacklist %s'),
$service->getObjectName(),
$host->getObjectName()
);
$this->redirectOnSuccess($msg);
}
}
/**
* @param IcingaService $service
* @return $this
* @throws ProgrammingError
*/
public function createApplyRuleFor(IcingaService $service)
{
$this->apply = $service;
@ -118,6 +277,9 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @throws \Zend_Form_Exception
*/
protected function setupServiceElements()
{
if ($this->object) {
@ -144,6 +306,10 @@ class IcingaServiceForm extends DirectorObjectForm
->setButtons();
}
/**
* @throws IcingaException
* @throws ProgrammingError
*/
protected function addOverrideHint()
{
if ($this->object && $this->object->usesVarOverrides()) {
@ -204,6 +370,10 @@ class IcingaServiceForm extends DirectorObjectForm
$this->addHtmlHint($hint, ['name' => 'inheritance_hint']);
}
/**
* @throws IcingaException
* @throws ProgrammingError
*/
protected function setupOnHostForSet()
{
$msg = $this->translate(
@ -248,6 +418,9 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @throws \Zend_Form_Exception
*/
protected function setupHostRelatedElements()
{
$this->addHidden('host_id', $this->host->id);
@ -291,6 +464,9 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @throws \Zend_Form_Exception
*/
protected function setupSetRelatedElements()
{
$this->addHidden('service_set_id', $this->set->id);
@ -333,6 +509,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @return $this
* @throws \Zend_Form_Exception
*/
protected function addNameElement()
{
$this->addElement('text', 'object_name', array(
@ -350,6 +530,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @return $this
* @throws \Zend_Form_Exception
*/
protected function addHostObjectElement()
{
if ($this->isObject()) {
@ -366,6 +550,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @return $this
* @throws \Zend_Form_Exception
*/
protected function addApplyForElement()
{
if ($this->object->isApplyRule()) {
@ -392,6 +580,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @return $this
* @throws \Zend_Form_Exception
*/
protected function addGroupsElement()
{
$groups = $this->enumServicegroups();
@ -415,6 +607,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $this;
}
/**
* @return $this
* @throws \Zend_Form_Exception
*/
protected function addAgentAndZoneElements()
{
if (!$this->isTemplate()) {
@ -470,6 +666,10 @@ class IcingaServiceForm extends DirectorObjectForm
return $db->fetchPairs($select);
}
/**
* @throws IcingaException
* @throws ProgrammingError
*/
protected function succeedForOverrides()
{
$vars = array();
@ -502,6 +702,10 @@ class IcingaServiceForm extends DirectorObjectForm
$this->redirectOnSuccess($msg);
}
/**
* @throws IcingaException
* @throws ProgrammingError
*/
public function onSuccess()
{
if ($this->providesOverrides()) {

View File

@ -6,6 +6,7 @@ use Icinga\Exception\ProgrammingError;
use Icinga\Module\Director\CustomVariable\CustomVariable;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Resolver\HostServiceBlacklist;
use Icinga\Module\Director\Resolver\TemplateTree;
/**
@ -31,6 +32,8 @@ class PrefetchCache
protected $templateTrees = array();
protected $hostServiceBlacklist;
public static function initialize(Db $db)
{
self::$instance = new static($db);
@ -101,6 +104,15 @@ class PrefetchCache
}
}
public function hostServiceBlacklist()
{
if ($this->hostServiceBlacklist === null) {
$this->hostServiceBlacklist = new HostServiceBlacklist($this->db);
}
return $this->hostServiceBlacklist;
}
/**
* @param IcingaObject $object
* @return CustomVariableCache

View File

@ -412,7 +412,7 @@ class IcingaService extends IcingaObject
$blacklist = $this->getBlacklistedHostnames();
if (! empty($blacklist)) {
$output .= sprintf(
" ignore where host.name IN %s\n",
" ignore where host.name in %s\n",
c::renderArray($blacklist)
);
}

View File

@ -781,14 +781,15 @@ abstract class DirectorObjectForm extends DirectorForm
} catch (Exception $e) {
$this->addUniqueException($e);
}
if ($this->shouldBeDeleted()) {
$this->deleteObject($this->object());
}
}
protected function handlePost()
{
$object = $this->object();
if ($this->shouldBeDeleted()) {
$this->deleteObject($object);
}
$post = $this->getRequest()->getPost();
$this->populate($post);

View File

@ -52,6 +52,12 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable
public function renderRow($row)
{
if ($row->blacklisted === 'y') {
$attributes = ['class' => 'strike-links'];
} else {
$attributes = null;
}
return $this::row([
Link::create(
sprintf(
@ -65,7 +71,7 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable
'service_id' => $row->id,
]
)
]);
], $attributes);
}
public function prepareQuery()
@ -82,7 +88,8 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable
return $ds->select()->columns([
'id' => 'id',
'name' => 'name',
'filter' => 'filter',
'filter' => 'filter',
'blacklisted' => 'blacklisted',
'assign_filter' => 'assign_filter',
]);
}
@ -108,8 +115,13 @@ class IcingaHostAppliedServicesTable extends SimpleQueryBasedTable
'id' => 's.id',
'name' => 's.object_name',
'assign_filter' => 's.assign_filter',
'blacklisted' => "CASE WHEN hsb.service_id IS NULL THEN 'n' ELSE 'y' END",
]
)->where('object_type = ? AND assign_filter IS NOT NULL', 'apply');
)->joinLeft(
['hsb' => 'icinga_host_service_blacklist'],
's.id = hsb.service_id',
[]
)->group('s.id')->where('object_type = ? AND assign_filter IS NOT NULL', 'apply');
return $db->fetchAll($query);
}

View File

@ -78,6 +78,12 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
return $parent;
}
/**
* @param $row
* @return Link
* @throws \Icinga\Exception\IcingaException
* @throws \Icinga\Exception\ProgrammingError
*/
protected function getServiceLink($row)
{
if ($this->affectedHost) {
@ -111,6 +117,9 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
if ($row->disabled === 'y') {
$tr->getAttributes()->add('class', 'disabled');
}
if ($row->blacklisted === 'y') {
$tr->getAttributes()->add('class', 'strike-links');
}
return $tr;
}
@ -125,6 +134,11 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
return $this->title ?: $this->translate('Servicename');
}
/**
* @param HtmlElement $parent
* @throws \Icinga\Exception\IcingaException
* @throws \Icinga\Exception\ProgrammingError
*/
protected function addHostHeaderTo(HtmlElement $parent)
{
if (! $this->host) {
@ -164,9 +178,14 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
$parent->add($this::th([$this->getTitle(), $deleteLink]));
}
/**
* @return \Zend_Db_Select
* @throws \Icinga\Exception\IcingaException
* @throws \Zend_Db_Select_Exception
*/
public function prepareQuery()
{
return $this->db()->select()->from(
$query = $this->db()->select()->from(
['s' => 'icinga_service'],
[
'id' => 's.id',
@ -185,5 +204,19 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
's.service_set_id = ?',
$this->set->get('id')
)->order('s.object_name');
if ($this->affectedHost) {
$query->joinLeft(
['hsb' => 'icinga_host_service_blacklist'],
's.id = hsb.service_id',
[]
)->group('s.id')->columns([
'blacklisted' => "CASE WHEN hsb.service_id IS NULL THEN 'n' ELSE 'y' END",
]);
} else {
$query->columns(['blacklisted' => "'n'"]);
}
return $query;
}
}

View File

@ -380,7 +380,7 @@ form dl {
padding: 0;
}
.strike-links a {
.strike-links a, table.common-table .strike-links a {
text-decoration: line-through;
&:hover {
text-decoration: line-through;