Skip to content

Commit

Permalink
VolatileStateResults: Properly apply state changes in case of Depende…
Browse files Browse the repository at this point in the history
…cyNode

- Use host behaviors for sevice hosts. Previously, the service behaviors was used.
  • Loading branch information
sukhwinder33445 committed Nov 19, 2024
1 parent e96f2a4 commit 8b0a944
Showing 1 changed file with 58 additions and 37 deletions.
95 changes: 58 additions & 37 deletions library/Icingadb/Redis/VolatileStateResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
use Icinga\Module\Icingadb\Common\IcingaRedis;
use Icinga\Module\Icingadb\Model\DependencyNode;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Icingadb\Model\HostState;
use Icinga\Module\Icingadb\Model\Service;
use Icinga\Module\Icingadb\Model\ServiceState;
use Icinga\Module\Icingadb\Model\State;
use ipl\Orm\Behaviors;
use ipl\Orm\Query;
use ipl\Orm\Resolver;
use ipl\Orm\ResultSet;
Expand All @@ -28,6 +32,12 @@ class VolatileStateResults extends ResultSet
/** @var bool Whether Redis updates were applied */
private $updatesApplied = false;

/** @var string Object type host */
private const TYPE_HOST = 'host';

/** @var string Object type service */
private const TYPE_SERVICE = 'service';

public static function fromQuery(Query $query)
{
$self = parent::fromQuery($query);
Expand Down Expand Up @@ -99,68 +109,89 @@ public function rewind(): void
protected function applyRedisUpdates($rows)
{
$type = null;
$behaviors = null;

$keys = [];
$hostStateKeys = [];

$showSourceGranted = $this->getAuth()->hasPermission('icingadb/object/show-source');

$getKeysAndBehaviors = function (State $state): array {
return [$state->getColumns(), $this->resolver->getBehaviors($state)];
};

$states = [];
$hostStates = [];
foreach ($rows as $row) {
if ($row instanceof DependencyNode) {
if ($row->redundancy_group_id !== null) {
continue;
} elseif ($row->service_id !== null) {
$type = 'service';
$type = self::TYPE_SERVICE;
$row = $row->service;
} else {
$type = 'host';
$type = self::TYPE_HOST;
$row = $row->host;
}

$behaviors = $this->resolver->getBehaviors($row->state);
} elseif ($type === null) {
$behaviors = $this->resolver->getBehaviors($row->state);

switch (true) {
case $row instanceof Host:
$type = 'host';
$type = self::TYPE_HOST;
break;
case $row instanceof Service:
$type = 'service';
$type = self::TYPE_SERVICE;
break;
default:
throw new RuntimeException('Volatile states can only be fetched for hosts and services');
}
}

$states[bin2hex($row->id)] = $row->state;
if (empty($keys)) {
$keys = $row->state->getColumns();
$states[$type][bin2hex($row->id)] = $row->state;

if (! isset($states[$type]['keys'])) {
[$keys, $behaviors] = $getKeysAndBehaviors($row->state);

if (! $showSourceGranted) {
$keys = array_diff($keys, ['check_commandline']);
}

$states[$type]['keys'] = $keys;
$states[$type]['behaviors'] = $behaviors;
}

if ($type === 'service' && $row->host instanceof Host && isset($row->host->id)) {
$hostStates[bin2hex($row->host->id)] = $row->host->state;
if (empty($hostStateKeys)) {
$hostStateKeys = $row->host->state->getColumns();
if ($type === self::TYPE_SERVICE && $row->host instanceof Host && isset($row->host->id)) {
$states[self::TYPE_HOST][bin2hex($row->host->id)] = $row->host->state;

if (! isset($states[self::TYPE_HOST]['keys'])) {
[$keys, $behaviors] = $getKeysAndBehaviors($row->host->state);

$states[self::TYPE_HOST]['keys'] = $keys;
$states[self::TYPE_HOST]['behaviors'] = $behaviors;
}
}
}

if (empty($states)) {
return;
if (! empty($states[self::TYPE_SERVICE])) {
$this->apply($states[self::TYPE_SERVICE], self::TYPE_SERVICE);
}

if ($type === 'service') {
$results = IcingaRedis::fetchServiceState(array_keys($states), $keys);
} else {
$results = IcingaRedis::fetchHostState(array_keys($states), $keys);
if (! empty($states[self::TYPE_HOST])) {
$this->apply($states[self::TYPE_HOST], self::TYPE_HOST);
}
}

/**
* Apply the given states of given type to the results
*
* @param array<string, string[]|HostState|ServiceState|Behaviors> $states
* @param string $type The object type ({@see self::TYPE_HOST} OR {@see self::TYPE_SERVICE})
*
* @return void
*/
protected function apply(array $states, string $type): void
{
$keys = $states['keys'];
$behaviors = $states['behaviors'];

unset($states['keys'], $states['behaviors']);

$results = $type === self::TYPE_SERVICE
? IcingaRedis::fetchServiceState(array_keys($states), $keys)
: IcingaRedis::fetchHostState(array_keys($states), $keys);

foreach ($results as $id => $data) {
foreach ($data as $key => $value) {
Expand All @@ -169,15 +200,5 @@ protected function applyRedisUpdates($rows)

$states[$id]->setProperties($data);
}

if ($type === 'service' && ! empty($hostStates)) {
foreach (IcingaRedis::fetchHostState(array_keys($hostStates), $hostStateKeys) as $id => $data) {
foreach ($data as $key => $value) {
$data[$key] = $behaviors->retrieveProperty($value, $key);
}

$hostStates[$id]->setProperties($data);
}
}
}
}

0 comments on commit 8b0a944

Please sign in to comment.