diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
commit | 8ca6cc32b2c789a3149861159ad258f2cb9491e3 (patch) | |
tree | 2492de6f1528dd44eaa169a5c1555026d9cb75ec /modules/migrate/application/clicommands/NavigationCommand.php | |
parent | Initial commit. (diff) | |
download | icingaweb2-upstream.tar.xz icingaweb2-upstream.zip |
Adding upstream version 2.11.4.upstream/2.11.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/migrate/application/clicommands/NavigationCommand.php')
-rw-r--r-- | modules/migrate/application/clicommands/NavigationCommand.php | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/modules/migrate/application/clicommands/NavigationCommand.php b/modules/migrate/application/clicommands/NavigationCommand.php new file mode 100644 index 0000000..06fb2a8 --- /dev/null +++ b/modules/migrate/application/clicommands/NavigationCommand.php @@ -0,0 +1,195 @@ +<?php + +/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Module\Migrate\Clicommands; + +use Icinga\Application\Config; +use Icinga\Application\Icinga; +use Icinga\Application\Logger; +use Icinga\Cli\Command; +use Icinga\Data\ConfigObject; +use Icinga\Exception\NotReadableError; +use Icinga\Exception\NotWritableError; +use Icinga\Module\Icingadb\Compat\UrlMigrator; +use Icinga\Util\DirectoryIterator; +use Icinga\Web\Request; +use ipl\Web\Filter\QueryString; +use ipl\Web\Url; + +class NavigationCommand extends Command +{ + /** + * Migrate local user monitoring navigation items to the Icinga DB Web actions + * + * USAGE + * + * icingacli migrate navigation [options] + * + * OPTIONS: + * + * --user=<username> Migrate monitoring navigation items only for + * the given user. (Default *) + * + * --delete Remove the legacy files after successfully + * migrated the navigation items. + */ + public function indexAction() + { + $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.'); + return; + } + + $preferencesPath = Config::resolvePath('preferences'); + $sharedNavigation = Config::resolvePath('navigation'); + if (! file_exists($preferencesPath) && ! file_exists($sharedNavigation)) { + Logger::info('There are no local user navigation items to migrate'); + return; + } + + $rc = 0; + $user = $this->params->get('user'); + $directories = new DirectoryIterator($preferencesPath); + + foreach ($directories as $directory) { + $username = $user; + if ($username !== null && $directories->key() !== $username) { + continue; + } + + if ($username === null) { + $username = $directories->key(); + } + + $hostActions = $this->readFromIni($directory . '/host-actions.ini', $rc); + $serviceActions = $this->readFromIni($directory . '/service-actions.ini', $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', $rc); + } + + if (! $serviceActions->isEmpty()) { + $this->migrateNavigationItems($serviceActions, $directory . '/icingadb-service-actions.ini', $rc); + } + } + + // Start migrating shared navigation items + $hostActions = $this->readFromIni($sharedNavigation . '/host-actions.ini', $rc); + $serviceActions = $this->readFromIni($sharedNavigation . '/service-actions.ini', $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', $rc); + } + + if (! $serviceActions->isEmpty()) { + $this->migrateNavigationItems($serviceActions, $sharedNavigation . '/icingadb-service-actions.ini', $rc); + } + + if ($rc > 0) { + Logger::error('Failed to migrate some monitoring navigation items'); + exit($rc); + } + + Logger::info('Successfully migrated all local user monitoring navigation items'); + } + + /** + * Migrate the given config to the given new config path + * + * @param Config $config + * @param string $path + * @param int $rc + */ + private function migrateNavigationItems($config, $path, &$rc) + { + $deleteLegacyFiles = $this->params->get('delete'); + $newConfig = $this->readFromIni($path, $rc); + $counter = 1; + + /** @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'; + } + + $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 + } + } + + $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); + } + } + + $section = $config->key(); + while ($newConfig->hasSection($section)) { + $section = $config->key() . $counter++; + } + + $newConfig->setSection($section, $configObject); + } + + try { + if (! $newConfig->isEmpty()) { + $newConfig->saveIni(); + + // Remove the legacy file only if explicitly requested + if ($deleteLegacyFiles) { + unlink($config->getConfigFile()); + } + } + } catch (NotWritableError $error) { + Logger::error('%s: %s', $error->getMessage(), $error->getPrevious()->getMessage()); + $rc = 256; + } + } + + /** + * Get the navigation items config from the given ini path + * + * @param string $path Absolute path of the ini file + * @param int $rc The return code used to exit the action + * + * @return Config + */ + private function readFromIni($path, &$rc) + { + try { + $config = Config::fromIni($path); + } catch (NotReadableError $error) { + if ($error->getPrevious() !== null) { + Logger::error('%s: %s', $error->getMessage(), $error->getPrevious()->getMessage()); + } else { + Logger::error($error->getMessage()); + } + + $config = new Config(); + $rc = 128; + } + + return $config; + } +} |