Skip to content

Commit

Permalink
ToicingadbCommand: Migrate legacy wildcard filters in Icinga DB Web a…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
raviks789 committed Oct 30, 2023
1 parent 6d97467 commit 0dcb763
Showing 1 changed file with 172 additions and 71 deletions.
243 changes: 172 additions & 71 deletions modules/migrate/application/clicommands/ToicingadbCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,28 @@
use Icinga\Web\Request;
use ipl\Web\Filter\QueryString;
use ipl\Web\Url;
use ipl\Stdlib\Filter;

class ToicingadbCommand extends Command
{
public function init(): void
{
if (! Icinga::app()->getModuleManager()->hasEnabled('icingadb')) {
$moduleManager = Icinga::app()->getModuleManager();
if (! $moduleManager->hasEnabled('icingadb')) {
Logger::error('Icinga DB module is not enabled. Please verify that the module is installed and enabled.');
exit;
}

$icingadbVersion = $moduleManager->getModule('icingadb')->getVersion();
if (version_compare($icingadbVersion, '1.1.0', '<')) {
Logger::error(
'Required Icinga DB Web version 1.1.0 or greater to run this migration. '
. 'Please upgrade your Icinga DB Web module.'
);
exit;
}

Logger::getInstance()->setLevel(Logger::INFO);
}

/**
Expand Down Expand Up @@ -69,39 +82,74 @@ public function navigationAction(): void

$hostActions = $this->readFromIni($directory . '/host-actions.ini', $rc);
$serviceActions = $this->readFromIni($directory . '/service-actions.ini', $rc);
$icingadbHostActions = $this->readFromIni($directory . '/icingadb-host-actions.ini', $rc);
$icingadbServiceActions = $this->readFromIni($directory . '/icingadb-service-actions.ini', $rc);

Logger::info(
'Transforming legacy wildcard filters of existing Icinga DB Web actions for user "%s"',
$username
);

if (! $icingadbServiceActions->isEmpty()) {
$this->migrateNavigationItems($icingadbHostActions, false, $rc);
}

if (! $icingadbServiceActions->isEmpty()) {
$this->migrateNavigationItems(
$icingadbServiceActions,
false,
$rc
);
}

Logger::info('Migrating monitoring navigation items for user "%s" to the Icinga DB Web actions', $username);

if (! $hostActions->isEmpty()) {
$this->migrateNavigationItems($hostActions, $directory . '/icingadb-host-actions.ini', false, $rc);
$this->migrateNavigationItems($hostActions, false, $rc, $directory . '/icingadb-host-actions.ini');
}

if (! $serviceActions->isEmpty()) {
$this->migrateNavigationItems(
$serviceActions,
$directory . '/icingadb-service-actions.ini',
false,
$rc
$rc,
$directory . '/icingadb-service-actions.ini'
);
}
}

// Start migrating shared navigation items
$hostActions = $this->readFromIni($sharedNavigation . '/host-actions.ini', $rc);
$serviceActions = $this->readFromIni($sharedNavigation . '/service-actions.ini', $rc);
$icingadbHostActions = $this->readFromIni($sharedNavigation . '/icingadb-host-actions.ini', $rc);
$icingadbServiceActions = $this->readFromIni($sharedNavigation . '/icingadb-service-actions.ini', $rc);

Logger::info('Transforming legacy wildcard filters of existing shared Icinga DB Web actions');

if (! $icingadbServiceActions->isEmpty()) {
$this->migrateNavigationItems($icingadbHostActions, true, $rc);
}

if (! $icingadbServiceActions->isEmpty()) {
$this->migrateNavigationItems(
$icingadbServiceActions,
true,
$rc
);
}

Logger::info('Migrating shared monitoring navigation items to the Icinga DB Web actions');

if (! $hostActions->isEmpty()) {
$this->migrateNavigationItems($hostActions, $sharedNavigation . '/icingadb-host-actions.ini', true, $rc);
$this->migrateNavigationItems($hostActions, true, $rc, $sharedNavigation . '/icingadb-host-actions.ini');
}

if (! $serviceActions->isEmpty()) {
$this->migrateNavigationItems(
$serviceActions,
$sharedNavigation . '/icingadb-service-actions.ini',
true,
$rc
$rc,
$sharedNavigation . '/icingadb-service-actions.ini'
);
}

Expand All @@ -117,89 +165,113 @@ public function navigationAction(): void
* Migrate the given config to the given new config path
*
* @param Config $config
* @param string $path
* @param ?string $path
* @param bool $shared
* @param int $rc
*/
private function migrateNavigationItems($config, $path, $shared, &$rc): void
private function migrateNavigationItems($config, $shared, &$rc, $path = null): void
{
$deleteLegacyFiles = $this->params->get('delete');
$override = $this->params->get('override');
$newConfig = $this->readFromIni($path, $rc);

/** @var ConfigObject $configObject */
foreach ($config->getConfigObject() as $configObject) {
// Change the config type from "host-action" to icingadb's new action
if (strpos($path, 'icingadb-host-actions') !== false) {
$configObject->type = 'icingadb-host-action';
} else {
$configObject->type = 'icingadb-service-action';
}

/** @var ?string $urlString */
$urlString = $configObject->get('url');
if ($urlString !== null) {
$url = Url::fromPath($urlString, [], new Request());

try {
$urlString = UrlMigrator::transformUrl($url)->getAbsoluteUrl();
$configObject->url = rawurldecode($urlString);
} catch (\InvalidArgumentException $err) {
// Do nothing
if ($path === null) {
$newConfig = $config;
/** @var ConfigObject $newConfigObject */
foreach ($newConfig->getConfigObject() as $section => $newConfigObject) {
/** @var ?string $legacyFilter */
$legacyFilter = $newConfigObject->get('filter');
if ($legacyFilter !== null) {
$filter = QueryString::parse($legacyFilter);
$filter = $this->transformLegacyWildcardFilter($filter);
if ($filter) {
$filter = rawurldecode(QueryString::render($filter));
$newConfigObject->filter = $filter;
$newConfig->setSection($section, $newConfigObject);
Logger::info(
'Wildcard filter "%s" of Icinga DB Web action "%s" is transformed to "%s"',
$legacyFilter,
$section,
$filter
);
}
}
}

/** @var ?string $legacyFilter */
$legacyFilter = $configObject->get('filter');
if ($legacyFilter !== null) {
$filter = QueryString::parse($legacyFilter);
$filter = UrlMigrator::transformFilter($filter);
if ($filter !== false) {
$configObject->filter = rawurldecode(QueryString::render($filter));
} else {
$deleteLegacyFiles = $this->params->get('delete');
$override = $this->params->get('override');
$newConfig = $this->readFromIni($path, $rc);

/** @var ConfigObject $configObject */
foreach ($config->getConfigObject() as $configObject) {
// Change the config type from "host-action" to icingadb's new action
if (strpos($path, 'icingadb-host-actions') !== false) {
$configObject->type = 'icingadb-host-action';
} else {
unset($configObject->filter);
$configObject->type = 'icingadb-service-action';
}

/** @var ?string $urlString */
$urlString = $configObject->get('url');
if ($urlString !== null) {
$url = Url::fromPath($urlString, [], new Request());

try {
$urlString = UrlMigrator::transformUrl($url)->getAbsoluteUrl();
$configObject->url = rawurldecode($urlString);
} catch (\InvalidArgumentException $err) {
// Do nothing
}
}
}

$section = $config->key();

if (! $newConfig->hasSection($section) || $override) {
/** @var string $owner */
$owner = $configObject->get('owner');
/** @var string $type */
$type = $configObject->get('type');
$oldPath = $shared
? sprintf(
'%s/%s/%ss.ini',
Config::resolvePath('preferences'),
$owner,
$type
)
: sprintf(
'%s/%ss.ini',
Config::resolvePath('navigation'),
$type
);

$oldConfig = $this->readFromIni($oldPath, $rc);

if ($override && $oldConfig->hasSection($section)) {
$oldConfig->removeSection($section);
$oldConfig->saveIni();
/** @var ?string $legacyFilter */
$legacyFilter = $configObject->get('filter');
if ($legacyFilter !== null) {
$filter = QueryString::parse($legacyFilter);
$filter = UrlMigrator::transformFilter($filter);
if ($filter !== false) {
$configObject->filter = rawurldecode(QueryString::render($filter));
} else {
unset($configObject->filter);
}
}

if (! $oldConfig->hasSection($section)) {
$newConfig->setSection($section, $configObject);
$section = $config->key();

if (!$newConfig->hasSection($section) || $override) {
/** @var string $owner */
$owner = $configObject->get('owner');
/** @var string $type */
$type = $configObject->get('type');
$oldPath = $shared
? sprintf(
'%s/%s/%ss.ini',
Config::resolvePath('preferences'),
$owner,
$type
)
: sprintf(
'%s/%ss.ini',
Config::resolvePath('navigation'),
$type
);

$oldConfig = $this->readFromIni($oldPath, $rc);

if ($override && $oldConfig->hasSection($section)) {
$oldConfig->removeSection($section);
$oldConfig->saveIni();
}

if (!$oldConfig->hasSection($section)) {
$newConfig->setSection($section, $configObject);
}
}
}
}

try {
if (! $newConfig->isEmpty()) {
if (!$newConfig->isEmpty()) {
$newConfig->saveIni();

// Remove the legacy file only if explicitly requested
if ($deleteLegacyFiles) {
if ($path !== null && $deleteLegacyFiles) {
unlink($config->getConfigFile());
}
}
Expand Down Expand Up @@ -234,4 +306,33 @@ private function readFromIni($path, &$rc)

return $config;
}

/**
* Transform given legacy wirldcard filters
*
* @param $filter Filter\Rule
*
* @return Filter\Chain|Filter\Condition|null
*/
private function transformLegacyWildcardFilter(Filter\Rule $filter)
{
if ($filter instanceof Filter\Chain) {
foreach ($filter as $child) {
$newChild = $this->transformLegacyWildcardFilter($child);
if ($newChild !== null) {
$filter->replace($child, $newChild);
}
}

return $filter;
} elseif ($filter instanceof Filter\Equal) {
if (is_string($filter->getValue()) && strpos($filter->getValue(), '*') !== false) {
return Filter::like($filter->getColumn(), $filter->getValue());
}
} elseif ($filter instanceof Filter\Unequal) {
if (is_string($filter->getValue()) && strpos($filter->getValue(), '*') !== false) {
return Filter::unlike($filter->getColumn(), $filter->getValue());
}
}
}
}

0 comments on commit 0dcb763

Please sign in to comment.