From c2543454b16f8d6024d8bfce1e5e23170ea8a7a8 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2025 16:15:55 +0200 Subject: [PATCH 1/3] migrate: Drop backend selection --- application/controllers/MigrateController.php | 66 ------ application/forms/SetAsBackendForm.php | 34 ---- library/Icingadb/Hook/IcingadbSupportHook.php | 7 +- public/css/widget/migrate-popup.less | 18 -- public/js/migrate.js | 192 +----------------- 5 files changed, 3 insertions(+), 314 deletions(-) delete mode 100644 application/forms/SetAsBackendForm.php diff --git a/application/controllers/MigrateController.php b/application/controllers/MigrateController.php index c14eef7e..e06783f1 100644 --- a/application/controllers/MigrateController.php +++ b/application/controllers/MigrateController.php @@ -5,16 +5,9 @@ namespace Icinga\Module\Icingadb\Controllers; use Exception; -use GuzzleHttp\Psr7\ServerRequest; -use Icinga\Application\Hook; -use Icinga\Application\Icinga; use Icinga\Exception\IcingaException; use Icinga\Module\Icingadb\Compat\UrlMigrator; -use Icinga\Module\Icingadb\Forms\SetAsBackendForm; -use Icinga\Module\Icingadb\Hook\IcingadbSupportHook; use Icinga\Module\Icingadb\Web\Controller; -use ipl\Html\HtmlString; -use ipl\Stdlib\Filter; use ipl\Web\Filter\QueryString; use ipl\Web\Url; @@ -107,63 +100,4 @@ class MigrateController extends Controller $response->sendResponse(); } - - public function checkboxStateAction() - { - $this->assertHttpMethod('get'); - - $form = new SetAsBackendForm(); - $form->setAction(Url::fromPath('icingadb/migrate/checkbox-submit')->getAbsoluteUrl()); - - $this->getDocument()->addHtml($form); - } - - public function checkboxSubmitAction() - { - $this->assertHttpMethod('post'); - $this->addPart(HtmlString::create('"bogus"'), 'Behavior:Migrate'); - - (new SetAsBackendForm())->handleRequest(ServerRequest::fromGlobals()); - } - - public function backendSupportAction() - { - $this->assertHttpMethod('post'); - if (! $this->getRequest()->isApiRequest()) { - $this->httpBadRequest('No API request'); - } - - if ( - ! preg_match('/([^;]*);?/', $this->getRequest()->getHeader('Content-Type'), $matches) - || $matches[1] !== 'application/json' - ) { - $this->httpBadRequest('No JSON content'); - } - - $moduleSupportStates = []; - if ( - Icinga::app()->getModuleManager()->hasEnabled('monitoring') - && $this->Auth()->hasPermission('module/monitoring') - ) { - $supportList = []; - foreach (Hook::all('Icingadb/IcingadbSupport') as $hook) { - /** @var IcingadbSupportHook $hook */ - $supportList[$hook->getModule()->getName()] = $hook->supportsIcingaDb(); - } - - $moduleSupportStates = []; - foreach ($this->getRequest()->getPost() as $moduleName) { - if (isset($supportList[$moduleName])) { - $moduleSupportStates[] = $supportList[$moduleName]; - } else { - $moduleSupportStates[] = false; - } - } - } - - $this->getResponse() - ->json() - ->setSuccessData($moduleSupportStates) - ->sendResponse(); - } } diff --git a/application/forms/SetAsBackendForm.php b/application/forms/SetAsBackendForm.php deleted file mode 100644 index 28406335..00000000 --- a/application/forms/SetAsBackendForm.php +++ /dev/null @@ -1,34 +0,0 @@ - 'setAsBackendForm', - 'class' => 'icinga-controls' - ]; - - protected function assemble() - { - $this->addElement('checkbox', 'backend', [ - 'class' => 'autosubmit', - 'label' => t('Use Icinga DB As Backend'), - 'value' => IcingadbSupportHook::isIcingaDbSetAsPreferredBackend() - ]); - } - - public function onSuccess() - { - Session::getSession()->getNamespace('icingadb')->set( - IcingadbSupportHook::PREFERENCE_NAME, - $this->getElement('backend')->isChecked() - ); - } -} diff --git a/library/Icingadb/Hook/IcingadbSupportHook.php b/library/Icingadb/Hook/IcingadbSupportHook.php index 96cdd19d..40c5d55d 100644 --- a/library/Icingadb/Hook/IcingadbSupportHook.php +++ b/library/Icingadb/Hook/IcingadbSupportHook.php @@ -13,9 +13,6 @@ abstract class IcingadbSupportHook { use HookUtils; - /** @var string key name of preference */ - const PREFERENCE_NAME = 'icingadb.as_backend'; - /** * Return whether your module supports IcingaDB or not * @@ -33,9 +30,7 @@ abstract class IcingadbSupportHook */ final public static function isIcingaDbSetAsPreferredBackend(): bool { - return (bool) Session::getSession() - ->getNamespace('icingadb') - ->get(self::PREFERENCE_NAME, false); + return true; } /** diff --git a/public/css/widget/migrate-popup.less b/public/css/widget/migrate-popup.less index 8f9586b9..7e8dbf70 100644 --- a/public/css/widget/migrate-popup.less +++ b/public/css/widget/migrate-popup.less @@ -156,24 +156,6 @@ } } - form { - width: 100%; - - .control-group { - display: flex; - align-items: center; - - .control-label-group { - margin-right: .5em; - } - - label { - margin-left: auto; - } - } - } - - .search-migration-suggestions:not(:empty) ~ form, .search-migration-suggestions:not(:empty) ~ .monitoring-migration-suggestions:not(:empty) { margin-bottom: .5em; } diff --git a/public/js/migrate.js b/public/js/migrate.js index dddbaed8..7f81402c 100644 --- a/public/js/migrate.js +++ b/public/js/migrate.js @@ -13,7 +13,6 @@ ' \n' + '

Miss some results? Try the link(s) below

\n' + ' \n' + - '

Preview this in Icinga DB

\n' + ' \n' + '
\n' + ' \n' + @@ -36,11 +35,8 @@ super(icinga); this.knownMigrations = {}; - this.knownBackendSupport = {}; this.urlMigrationReadyState = null; - this.backendSupportReadyState = null; this.searchMigrationReadyState = null; - this.backendSupportRelated = {}; this.$popup = null; // Some persistence, we don't want to annoy our users too much @@ -60,19 +56,6 @@ this.storage.onChange('minimized', this.onMinimized, this); } - update(data) { - if (data !== 'bogus') { - return; - } - - $.each(this.backendSupportRelated, (id, _) => { - let $container = $('#' + id); - let req = this.icinga.loader.loadUrl($container.data('icingaUrl'), $container); - req.addToHistory = false; - req.scripted = true; - }); - } - onRendered(event) { var _this = event.data.self; var $target = $(event.target); @@ -111,7 +94,6 @@ prepareMigration($target) { let monitoringUrls = {}; let searchUrls = {}; - let modules = {} $target.each((_, container) => { let $container = $(container); @@ -132,11 +114,6 @@ } } } - - let moduleName = $container.data('icingaModule'); - if (!! moduleName && moduleName !== 'default' && moduleName !== 'monitoring' && moduleName !== 'icingadb') { - modules[containerId] = moduleName; - } }); if (Object.keys(monitoringUrls).length) { @@ -153,16 +130,8 @@ this.setSearchMigrationReadyState(null); } - if (Object.keys(modules).length) { - this.setBackendSupportReadyState(false); - this.prepareBackendCheckboxForm(modules); - } else { - this.setBackendSupportReadyState(null); - } - if ( this.urlMigrationReadyState === null - && this.backendSupportReadyState === null && this.searchMigrationReadyState === null ) { this.cleanupPopup(); @@ -193,21 +162,6 @@ } }); - let backendSupportRelated = { ..._this.backendSupportRelated }; - $.each(backendSupportRelated, (id, module) => { - let $container = $('#' + id); - if (! $container.length || $container.data('icingaModule') !== module) { - let $newContainer = $('#main > .container').filter(function () { - return $(this).data('icingaModule') === module; - }); - if ($newContainer.length) { - _this.backendSupportRelated[$newContainer.attr('id')] = module; - } - - delete _this.backendSupportRelated[id]; - } - }); - _this.cleanupPopup(); } @@ -239,7 +193,7 @@ _this.knownMigrations[containerUrl] = false; } - if (_this.Popup().find('li').length === 1 && ! _this.Popup().find('#setAsBackendForm').length) { + if (_this.Popup().find('li').length === 1) { _this.hidePopup(function () { // Let the transition finish first, looks cleaner $suggestion.remove(); @@ -329,87 +283,6 @@ this.addSuggestions(req.urls, req.suggestionType); } - prepareBackendCheckboxForm(modules) { - let containerIds = []; - let moduleNames = []; - - $.each(modules, (id, module) => { - if (typeof this.knownBackendSupport[module] === 'undefined') { - containerIds.push(id); - moduleNames.push(module); - } - }); - - if (moduleNames.length) { - let req = $.ajax({ - context : this, - type : 'post', - url : this.icinga.config.baseUrl + '/icingadb/migrate/backend-support', - headers : { 'Accept': 'application/json' }, - contentType : 'application/json', - data : JSON.stringify(moduleNames) - }); - - req.modules = modules; - req.moduleIndexToContainerId = containerIds; - req.done(this.processBackendSupportResults); - req.always(() => this.changeBackendSupportReadyState(true)); - } else { - // All modules have already been checked once, show popup immediately - this.setupBackendCheckboxForm(modules); - this.changeBackendSupportReadyState(true); - } - } - - processBackendSupportResults(data, textStatus, req) { - let result = data.data; - - $.each(result, (i, state) => { - let containerId = req.moduleIndexToContainerId[i]; - this.knownBackendSupport[req.modules[containerId]] = state; - }); - - this.setupBackendCheckboxForm(req.modules); - } - - setupBackendCheckboxForm(modules) { - let supportedModules = {}; - - $.each(modules, (id, module) => { - if (this.knownBackendSupport[module]) { - supportedModules[id] = module; - } - }); - - if (Object.keys(supportedModules).length) { - this.backendSupportRelated = { ...this.backendSupportRelated, ...supportedModules }; - - let req = $.ajax({ - context : this, - type : 'get', - url : this.icinga.config.baseUrl + '/icingadb/migrate/checkbox-state?showCompact' - }); - - req.done(this.setCheckboxState); - } - } - - setCheckboxState(html, textStatus, req) { - let $form = this.Popup().find('.suggestion-area > #setAsBackendForm'); - if (! $form.length) { - $form = $(html); - $form.attr('data-base-target', 'migrate-popup-backend-submit-blackhole'); - $form.append('
'); - - this.Popup().find('.monitoring-migration-suggestions').before($form); - } else { - let $newForm = $(html); - $form.find('[name=backend]').prop('checked', $newForm.find('[name=backend]').is(':checked')); - } - - this.showPopup(); - } - addSuggestions(urls, type) { var where; if (type === 'monitoring') { @@ -490,53 +363,21 @@ return toBeRemoved; } - cleanupBackendForm() { - let $form = this.Popup().find('#setAsBackendForm'); - if (! $form.length) { - return false; - } - - let stillRelated = {}; - $.each(this.backendSupportRelated, (id, module) => { - let $container = $('#' + id); - if ($container.length && $container.data('icingaModule') === module) { - stillRelated[id] = module; - } - }); - - this.backendSupportRelated = stillRelated; - - if (Object.keys(stillRelated).length) { - return true; - } - - return $form; - } - cleanupPopup() { let toBeRemoved = this.cleanupSuggestions(); - let hasBackendForm = this.cleanupBackendForm(); - if (hasBackendForm !== true && this.Popup().find('li').length === toBeRemoved.length) { + if (this.Popup().find('li').length === toBeRemoved.length) { this.hidePopup(() => { // Let the transition finish first, looks cleaner $.each(toBeRemoved, function (_, $suggestion) { $suggestion.remove(); }); - - if (typeof hasBackendForm === 'object') { - hasBackendForm.remove(); - } }); } else { $.each(toBeRemoved, function (_, $suggestion) { $suggestion.remove(); }); - if (typeof hasBackendForm === 'object') { - hasBackendForm.remove(); - } - // Let showPopup() handle the automatic minimization in case all search suggestions have been removed this.showPopup(); } @@ -599,13 +440,6 @@ changeUrlMigrationReadyState(state) { this.setUrlMigrationReadyState(state); - - if (this.backendSupportReadyState !== false && this.searchMigrationReadyState !== false) { - this.searchMigrationReadyState = null; - this.backendSupportReadyState = null; - this.urlMigrationReadyState = null; - this.cleanupPopup(); - } } setSearchMigrationReadyState(state) { @@ -614,28 +448,6 @@ changeSearchMigrationReadyState(state) { this.setSearchMigrationReadyState(state); - - if (this.backendSupportReadyState !== false && this.urlMigrationReadyState !== false) { - this.searchMigrationReadyState = null; - this.backendSupportReadyState = null; - this.urlMigrationReadyState = null; - this.cleanupPopup(); - } - } - - setBackendSupportReadyState(state) { - this.backendSupportReadyState = state; - } - - changeBackendSupportReadyState(state) { - this.setBackendSupportReadyState(state); - - if (this.urlMigrationReadyState !== false && this.searchMigrationReadyState !== false) { - this.searchMigrationReadyState = null; - this.backendSupportReadyState = null; - this.urlMigrationReadyState = null; - this.cleanupPopup(); - } } Popup() { From 5d068666d363d160618fe811be20029019d3f0f7 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2025 16:24:50 +0200 Subject: [PATCH 2/3] migrate: Drop monitoring url preview --- application/controllers/MigrateController.php | 50 ------------------- doc/10-Migration.md | 30 ----------- public/css/widget/migrate-popup.less | 8 +-- public/js/migrate.js | 47 ++--------------- 4 files changed, 6 insertions(+), 129 deletions(-) diff --git a/application/controllers/MigrateController.php b/application/controllers/MigrateController.php index e06783f1..945befe7 100644 --- a/application/controllers/MigrateController.php +++ b/application/controllers/MigrateController.php @@ -4,8 +4,6 @@ namespace Icinga\Module\Icingadb\Controllers; -use Exception; -use Icinga\Exception\IcingaException; use Icinga\Module\Icingadb\Compat\UrlMigrator; use Icinga\Module\Icingadb\Web\Controller; use ipl\Web\Filter\QueryString; @@ -13,54 +11,6 @@ use ipl\Web\Url; class MigrateController extends Controller { - public function monitoringUrlAction() - { - $this->assertHttpMethod('post'); - if (! $this->getRequest()->isApiRequest()) { - $this->httpBadRequest('No API request'); - } - - if ( - ! preg_match('/([^;]*);?/', $this->getRequest()->getHeader('Content-Type'), $matches) - || $matches[1] !== 'application/json' - ) { - $this->httpBadRequest('No JSON content'); - } - - $urls = $this->getRequest()->getPost(); - - $result = []; - $errors = []; - foreach ($urls as $urlString) { - $url = Url::fromPath($urlString); - if (UrlMigrator::isSupportedUrl($url)) { - try { - $urlString = rawurldecode(UrlMigrator::transformUrl($url)->getAbsoluteUrl()); - } catch (Exception $e) { - $errors[$urlString] = [ - IcingaException::describe($e), - IcingaException::getConfidentialTraceAsString($e) - ]; - $urlString = false; - } - } - - $result[] = $urlString; - } - - $response = $this->getResponse()->json(); - if (empty($errors)) { - $response->setSuccessData($result); - } else { - $response->setFailData([ - 'result' => $result, - 'errors' => $errors - ]); - } - - $response->sendResponse(); - } - public function searchUrlAction() { $this->assertHttpMethod('post'); diff --git a/doc/10-Migration.md b/doc/10-Migration.md index d5a3ec8d..087e3ab7 100644 --- a/doc/10-Migration.md +++ b/doc/10-Migration.md @@ -69,36 +69,6 @@ expects a username, with optional wildcards (`*`) to match multiple users. `--us Pass `--no-backup` to disable backup creation. Please note, if you do so, that this makes resetting changes more difficult. -### Automation - -For those who integrate Icinga Web into e.g. custom dashboards, there is also a way to automate the -migration of urls. An API endpoint in Icinga DB Web allows for this: - -`/icingaweb2/icingadb/migrate/monitoring-url` - -If you `POST` a JSON list there, you'll get a JSON list back with the transformed urls in it. -The returned list is ordered the same and any unrecognized url is left unchanged: - -**Input:** -```json -[ - "/icingaweb2/monitoring/list/services?hostgroup_name=prod-hosts|(_host_env=prod&_host_stage!=testing)", - "/icingaweb2/businessprocess/process/show?config=production" -] -``` - -**Output**: -```json -[ - "/icingaweb2/icingadb/services?hostgroup.name=prod-hosts|(host.vars.env=prod&host.vars.stage!=testing)", - "/icingaweb2/businessprocess/process/show?config=production" -] -``` - -**curl example:** -`curl -s -HContent-Type:application/json -HAccept:application/json -u icingaadmin:icinga http://localhost/icingaweb2/icingadb/migrate/monitoring-url -d '["/icingaweb2/monitoring/list/services?hostgroup_name=prod-hosts|(_host_env=prod&_host_stage!=testing)","/icingaweb2/businessprocess/process/show?config=production"]'` - - ## Views and Exports ### Url Parameter `addColumns` diff --git a/public/css/widget/migrate-popup.less b/public/css/widget/migrate-popup.less index 7e8dbf70..b4119a83 100644 --- a/public/css/widget/migrate-popup.less +++ b/public/css/widget/migrate-popup.less @@ -98,9 +98,7 @@ color: @text-color-light; } - form ~ .monitoring-migration-hint, - .search-migration-suggestions:not(:empty) + .search-migration-hint, - .monitoring-migration-suggestions:not(:empty) + .monitoring-migration-hint { + .search-migration-suggestions:not(:empty) + .search-migration-hint { display: block; } @@ -155,9 +153,5 @@ } } } - - .search-migration-suggestions:not(:empty) ~ .monitoring-migration-suggestions:not(:empty) { - margin-bottom: .5em; - } } } diff --git a/public/js/migrate.js b/public/js/migrate.js index 7f81402c..3766c539 100644 --- a/public/js/migrate.js +++ b/public/js/migrate.js @@ -12,7 +12,6 @@ ' \n' + ' \n' + '

Miss some results? Try the link(s) below

\n' + - ' \n' + ' \n' + '
\n' + ' \n' + @@ -35,7 +34,6 @@ super(icinga); this.knownMigrations = {}; - this.urlMigrationReadyState = null; this.searchMigrationReadyState = null; this.$popup = null; @@ -45,9 +43,6 @@ this.tempStorage.setBackend(window.sessionStorage); this.previousMigrations = {}; - // We don't want to ask the server to migrate non-monitoring urls - this.isMonitoringUrl = new RegExp('^' + icinga.config.baseUrl + '/monitoring/'); - this.on('rendered', this.onRendered, this); this.on('close-column', this.onColumnClose, this); this.on('click', '#migrate-popup button.close', this.onClose, this); @@ -92,7 +87,6 @@ } prepareMigration($target) { - let monitoringUrls = {}; let searchUrls = {}; $target.each((_, container) => { @@ -107,22 +101,13 @@ ) { delete this.previousMigrations[containerId]; } else { - if (href.match(this.isMonitoringUrl)) { - monitoringUrls[containerId] = href; - } else if ($container.find('[data-enrichment-type="search-bar"]').length) { + if ($container.find('[data-enrichment-type="search-bar"]').length) { searchUrls[containerId] = href; } } } }); - if (Object.keys(monitoringUrls).length) { - this.setUrlMigrationReadyState(false); - this.migrateUrls(monitoringUrls, 'monitoring'); - } else { - this.setUrlMigrationReadyState(null); - } - if (Object.keys(searchUrls).length) { this.setSearchMigrationReadyState(false); this.migrateUrls(searchUrls, 'search'); @@ -130,10 +115,7 @@ this.setSearchMigrationReadyState(null); } - if ( - this.urlMigrationReadyState === null - && this.searchMigrationReadyState === null - ) { + if (this.searchMigrationReadyState === null) { this.cleanupPopup(); } } @@ -230,14 +212,8 @@ } }); - let endpoint, changeCallback; - if (type === 'monitoring') { - endpoint = 'monitoring-url'; - changeCallback = this.changeUrlMigrationReadyState.bind(this); - } else { - endpoint = 'search-url'; - changeCallback = this.changeSearchMigrationReadyState.bind(this); - } + const endpoint = 'search-url'; + const changeCallback = this.changeSearchMigrationReadyState.bind(this); if (containerUrls.length) { var req = $.ajax({ @@ -284,12 +260,7 @@ } addSuggestions(urls, type) { - var where; - if (type === 'monitoring') { - where = '.monitoring-migration-suggestions'; - } else { - where = '.search-migration-suggestions'; - } + const where = '.search-migration-suggestions'; var _this = this, hasSuggestions = false, @@ -434,14 +405,6 @@ } } - setUrlMigrationReadyState(state) { - this.urlMigrationReadyState = state; - } - - changeUrlMigrationReadyState(state) { - this.setUrlMigrationReadyState(state); - } - setSearchMigrationReadyState(state) { this.searchMigrationReadyState = state; } From 6c31feb523764722d2b4421d466032be8d73e9f8 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2025 16:49:35 +0200 Subject: [PATCH 3/3] doc: Mention migration removal --- doc/05-Upgrading.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/05-Upgrading.md b/doc/05-Upgrading.md index 853e3e99..57bcb214 100644 --- a/doc/05-Upgrading.md +++ b/doc/05-Upgrading.md @@ -3,6 +3,14 @@ Specific version upgrades are described below. Please note that version upgrades are incremental. If you are upgrading across multiple versions, make sure to follow the steps for each of them. +## Upgrading to Icinga DB Web v1.3 + +**Removed Features** + +* The migration widget in the top right is not toggled anymore for monitoring views, nor does it allow choosing + the preferred backend type for modules with support for IDO and Icinga DB. The default backend type is now + always Icinga DB. + ## Upgrading to Icinga DB Web v1.2 **Requirements**